暑假集训8.7数据结构专题-很妙的线段树( 觉醒力量(hidpower))

Posted jessie-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暑假集训8.7数据结构专题-很妙的线段树( 觉醒力量(hidpower))相关的知识,希望对你有一定的参考价值。

题目:oj1710

因为存在修改和查询的操作,所以学长说可以很“轻易”的想到线段树....,装作我轻易的想到了,最后是要输出答案mod17及mod46189的结果,(关键点1)然后我们发现46189=11*13*17*19;于是我们想到但处理出答案mod每个质因数的答案,再利用中国剩余定理求出答案。(关键点2)考虑对枚举进入某各区间运算的数为1-p[i],因为p[i]很小所以可以处理。然后修改操作也变成log的。非常可写。

关于中国剩余定理:x=(∑ai*ti*mi)modM。ti是逆元。

上代码:

技术分享图片
#include<bits/stdc++.h>
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
string s[17]={"Fight","Flying","Poison","Ground","Rock","Bug","Ghost","Steel","Fire","Water","Grass","Electric","Psychic","Ice","Dragon","Dark","Fairy"};
const int N=1e5+5;int n,m,p[5]={0,11,13,17,19},k[5],P=46189;
struct node{char ch;int a;}q[N];struct data{int b[5][20];}t[N<<2];
int read(){int x,f=1;char ch;_(!)ch==-?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;}
int ksm(int x,int y,int p){int b=x,ans=1;while(y){if(y&1)ans=ans*b%p;b=b*b%p;y>>=1;}return ans;}
LL ksml(LL x,LL y,int p){LL b=x,ans=1;while(y){if(y&1)ans=ans*b%p;b=b*b%p;y>>=1;}return ans;}
il void update(int x){
    for(int i=1;i<=4;i++)
        for(int j=0;j<p[i];j++)
            t[x].b[i][j]=t[x<<1|1].b[i][t[x<<1].b[i][j]%p[i]];
}
void build(int x,int l,int r){
    if(l==r){
        for(int i=1;i<=4;i++){
            for(int j=0;j<p[i];j++){
                if(q[l].ch==+)t[x].b[i][j]=(j+q[l].a%p[i])%p[i];
                if(q[l].ch==-)t[x].b[i][j]=(j-q[l].a%p[i]+p[i])%p[i];
                if(q[l].ch==*)t[x].b[i][j]=q[l].a%p[i]*j%p[i];
                if(q[l].ch==^)t[x].b[i][j]=ksm(j,q[l].a,p[i])%p[i];
            }
        }
        return;
    }int mid=(l+r)>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    update(x);
}
void change(int x,int l,int r,int pos){
    if(l==r){
        for(int i=1;i<=4;i++)
            for(int j=0;j<p[i];j++){
                if(q[l].ch==+)t[x].b[i][j]=(j+q[l].a%p[i])%p[i];
                if(q[l].ch==-)t[x].b[i][j]=(j-q[l].a%p[i]+p[i])%p[i];
                if(q[l].ch==*)t[x].b[i][j]=q[l].a%p[i]*j%p[i];
                if(q[l].ch==^)t[x].b[i][j]=ksm(j,q[l].a,p[i]);
            }return;
    }int mid=(l+r)>>1;
    if(pos<=mid)change(x<<1,l,mid,pos);
    else change(x<<1|1,mid+1,r,pos);
    update(x);
}
int main()
{
  n=read();m=read();
  for(int i=1;i<=n;i++){cin>>q[i].ch;q[i].a=read();}
  build(1,1,n);for(int i=1;i<=4;i++)k[i]=ksml((LL)(P/p[i]),(LL)(p[i]-2),p[i]);
  for(int i=1;i<=m;i++){
    int op=read();int x,y;
    if(op==1){
          x=read();cout<<s[t[1].b[3][x%17]%17];LL ans=0;
          for(int i=1;i<=4;i++){ans=(ans+(LL)t[1].b[i][x%p[i]]*(LL)k[i]%P*(LL)(P/p[i])%P)%P;}
          printf(" %d
",ans);
        }
        else{x=read();cin>>q[x].ch;q[x].a=read();change(1,1,n,x);}
    }
  return 0;
}
View Code

 

以上是关于暑假集训8.7数据结构专题-很妙的线段树( 觉醒力量(hidpower))的主要内容,如果未能解决你的问题,请参考以下文章

暑假集训--线段树

2017暑假集训前总结和规划

2019暑假集训 8/2

很妙的思维模型整理

暑假集训-8.14总结

暑假集训test-8-30