• 【2019北京集训2】Elephant 平衡树


    题目大意:给你一个长度为$n$的序列$A_i$,有$q$次操作,每次操作为以下三种之一:

    询问区间的$F_M(A_i)$的最大公约数。

    区间翻转,区间加一个正数。

    我们定义$gcd(0,0)=0$,且$F_M(A_i)$为在一个$M$个点的无向完全图中从第一个点开始走$k$步后回到第一个点的方案数。

    数据范围:$n,q≤10^5$,$0≤A_i≤10^8$,$2≤M≤10^9$。

    我们先考虑下如何求$F_M(x)$。

    经过打表(大雾),我们发现:

    若$x$为偶数,则$F_M(x)=M imes(F_M(x-1)+1)$

    若$x$为奇数,则$F_M(x)=M imes(F_M(x-1)-1)$

    特别地,$F_M(0)=1$,$F_M(1)=0$

    我们显然可以$O(2 imes 10^8)$预处理或者直接矩阵快速幂计算。

    继续打表,我们发现:$gcd(F_M(x-1),F_M(y-1))=F_M(gcd(x-1,y-1))$,感兴趣的同学可以证明一下(反正我不会)

    我们发现,如果询问的区间中存在数字0,则这个区间的GCD显然为1

    考虑到要资瓷区间翻转,区间查询0的个数,区间抹去0,对于这部分我们需要单独开一棵splay来维护。

    考虑维护>1部分的数。

    我们先不考虑翻转的情况。

    我们将差分后的数列丢入一棵splay中,每个节点维护整棵子树内的权值和,还有子树内的GCD

    我们需要查询区间$[l,r]$的$GCD$时,我们只需要查询$[l+1,r]$的区间GCD,然后再和第$l$个位置的值求GCD即可输出。

    原因显然

    考虑翻转区间$[l,r]$的情况:不难发现受到影响的区间为$[l,r+1]$。

    然后,经过冷静分析(大雾),我们发现翻转前后有这样的性质:

    1,第$l$个位置的查分值和第$r+1$个位置的差分值需要单独更新。

    2,区间$[l+1,r]$内的差分值等于原区间$[l+1,r]$内的差分值翻转再取相反数。

    上面这张图是一个例子,证明显然。

    然后,我们开几个标记打一下就可以了。

    然后就没有然后了,注意细节

    时间复杂度:$O(nlog^2 n)$

      1 #include<bits/stdc++.h>
      2 #define M 200005
      3 #define MOD 323232323
      4 #define L long long
      5 #define lc(x) ch[(x)][0]
      6 #define rc(x) ch[(x)][1]
      7 using namespace std;
      8 
      9 int GCD(int x,int y){return __gcd(abs(x),abs(y));}
     10 
     11 struct mat{
     12     L a[3][3]; mat(){memset(a,0,sizeof(a));}
     13     void danwei(){a[0][0]=a[1][1]=a[2][2]=1;}
     14     friend mat operator *(mat a,mat b){
     15         mat c;
     16         for(int i=0;i<3;i++)
     17         for(int j=0;j<3;j++)
     18         for(int k=0;k<3;k++)
     19         c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%MOD;
     20         return c;
     21     }
     22     friend mat operator ^(mat x,int b){
     23         mat ans; ans.danwei();
     24         while(b){
     25             if(b&1) ans=ans*x;
     26             x=x*x; b>>=1;
     27         }
     28         return ans;
     29     }
     30 };
     31 L P;
     32 L getans(int n){
     33     if(n==0) return 0;
     34     mat a;
     35     a.a[0][1]=a.a[2][2]=1;
     36     a.a[1][0]=P*P%MOD;
     37     a.a[2][0]=(P-1+MOD)%MOD;
     38     a=a^(n-1);
     39     L res=a.a[2][0]*P%MOD;
     40     if(n&1) res=P*(res+1)%MOD;
     41     return res;
     42 }
     43 
     44 namespace FF{
     45     int siz[M]={0},ch[M][2]={0},sum[M]={0},tagf[M]={0},val[M]={0},rev[M]={0},fa[M]={0},use=0;
     46 
     47     int root=0;
     48     void pushup(int x){
     49         siz[x]=siz[lc(x)]+siz[rc(x)]+1;
     50         sum[x]=sum[lc(x)]+sum[rc(x)]+val[x];
     51     }
     52     void upd(int x){rev[x]^=1; swap(lc(x),rc(x)); }
     53     void cls(int x){tagf[x]=1; sum[x]=val[x]=0;}
     54     void pushdown(int x){
     55         if(rev[x]) upd(lc(x)),upd(rc(x)); rev[x]=0;
     56         if(tagf[x]) cls(lc(x)),cls(rc(x)); tagf[x]=0;
     57     }
     58     void rotate(int x,int &k){
     59         int y=fa[x],z=fa[y],l,r;
     60         l=(ch[y][0]!=x); r=l^1;
     61         if(y==k) k=x;
     62         else{
     63             if(lc(z)==y) ch[z][0]=x;
     64             else ch[z][1]=x;
     65         }
     66         fa[y]=x; fa[x]=z; fa[ch[x][r]]=y;
     67         ch[y][l]=ch[x][r]; ch[x][r]=y;
     68         pushup(y); pushup(x);
     69     }
     70     void pud(int x,int k){if(x!=k) pud(fa[x],k); pushdown(x);}
     71     
     72     void splay(int x,int &k){
     73         pud(x,k);
     74         while(x!=k){
     75             int y=fa[x],z=fa[y];
     76             if(y!=k){
     77                 if((lc(y)==x)==(lc(z)==y)) rotate(y,k);
     78                 else rotate(x,k);
     79             }
     80             rotate(x,k);
     81         }
     82     }
     83     int insert(int x,int id,int zhi){
     84         pushdown(x);
     85         if(!x){x=++use; val[x]=zhi;}
     86         else{
     87             if(siz[lc(x)]+1<=id) rc(x)=insert(rc(x),id-siz[lc(x)]-1,zhi),fa[rc(x)]=x; 
     88             else lc(x)=insert(lc(x),id,zhi),fa[lc(x)]=x;
     89         }
     90         pushup(x); return x;
     91     }
     92     int find(int x,int k){
     93         pushdown(x);
     94         if(siz[lc(x)]+1==k) return x;
     95         if(siz[lc(x)]>=k) return find(lc(x),k);
     96         return find(rc(x),k-siz[lc(x)]-1);
     97     }
     98     void ins(int x,int k){
     99         root=insert(root,k,x);
    100         splay(use,root);
    101     }
    102     
    103     int query(int x,int y){
    104         int X=find(root,x),Y=find(root,y+2);
    105         splay(X,root); splay(Y,rc(root));
    106         return sum[lc(Y)];
    107     }
    108     void updata(int x,int y){
    109         int X=find(root,x),Y=find(root,y+2);
    110         splay(X,root); splay(Y,rc(root));
    111         cls(lc(Y)); 
    112         pushup(Y); 
    113         pushup(root);
    114     }
    115     void setrev(int x,int y){
    116         int X=find(root,x),Y=find(root,y+2);
    117         splay(X,root); splay(Y,rc(root));
    118         upd(lc(Y));
    119     }
    120 }
    121 
    122 int siz[M]={0},ch[M][2]={0},gcd[M]={0},sum[M]={0},val[M]={0},rev[M]={0},fa[M]={0},use=0;
    123 
    124 int root=0;
    125 void pushup(int x){
    126     siz[x]=siz[lc(x)]+siz[rc(x)]+1;
    127     sum[x]=sum[lc(x)]+sum[rc(x)]+val[x];
    128     gcd[x]=GCD(GCD(gcd[lc(x)],gcd[rc(x)]),val[x]);
    129 }
    130 void upd(int x){rev[x]^=1; swap(lc(x),rc(x)); sum[x]=-sum[x]; val[x]=-val[x];}
    131 void pushdown(int x){if(rev[x]) upd(lc(x)),upd(rc(x)); rev[x]=0;}
    132 void rotate(int x,int &k){
    133     int y=fa[x],z=fa[y],l,r;
    134     l=(ch[y][0]!=x); r=l^1;
    135     if(y==k) k=x;
    136     else{
    137         if(lc(z)==y) ch[z][0]=x;
    138         else ch[z][1]=x;
    139     }
    140     fa[y]=x; fa[x]=z; fa[ch[x][r]]=y;
    141     ch[y][l]=ch[x][r]; ch[x][r]=y;
    142     pushup(y); pushup(x);
    143 }
    144 void pud(int x){if(x!=root) pud(fa[x]); pushdown(x);}
    145 
    146 void splay(int x,int &k){
    147     pud(x);
    148     while(x!=k){
    149         int y=fa[x],z=fa[y];
    150         if(y!=k){
    151             if((lc(y)==x)==(lc(z)==y)) rotate(y,k);
    152             else rotate(x,k);
    153         }
    154         rotate(x,k);
    155     }
    156 }
    157 int insert(int x,int id,int zhi){
    158     pushdown(x);
    159     if(!x){x=++use; val[x]=zhi;}
    160     else{
    161         if(siz[lc(x)]+1<=id) rc(x)=insert(rc(x),id-siz[lc(x)]-1,zhi),fa[rc(x)]=x; 
    162         else lc(x)=insert(lc(x),id,zhi),fa[lc(x)]=x;
    163     }
    164     pushup(x); return x;
    165 }
    166 int find(int x,int k){
    167     pushdown(x);
    168     if(siz[lc(x)]+1==k) return x;
    169     if(siz[lc(x)]>=k) return find(lc(x),k);
    170     return find(rc(x),k-siz[lc(x)]-1);
    171 }
    172 void ins(int x,int k){
    173     root=insert(root,k,x);
    174     splay(use,root);
    175 }
    176 void del(int k){
    177     int x=find(root,k); splay(x,root);
    178     int y=find(root,k+1); lc(y)=lc(x); 
    179     fa[lc(x)]=y; fa[rc(x)]=0; root=rc(x);
    180     splay(y,root); 
    181     
    182 }
    183 
    184 int getval(int id){
    185     int x=find(root,id+1);
    186     splay(x,root);
    187     return val[x]+sum[lc(x)];
    188 }
    189 int query(int x,int y){
    190     if(x>y) return 0;
    191     int X=find(root,x),Y=find(root,y+2);
    192     splay(X,root);
    193     splay(Y,rc(root));
    194     return gcd[lc(Y)];
    195 }
    196 void updata(int id,int delta){
    197     int x=find(root,id);
    198     splay(x,root);
    199     val[x]+=delta;
    200     pushup(x);
    201 }
    202 
    203 void setrev(int x,int y){
    204     int X=find(root,x),Y=find(root,y+2);
    205     splay(X,root);
    206     splay(Y,rc(root));
    207     upd(lc(Y));
    208     pushup(lc(Y)); 
    209     splay(lc(Y),root);
    210 }
    211 
    212 void setval(int x,int V){
    213     int X=find(root,x+1);
    214     splay(X,root);
    215     val[X]=V;
    216     pushup(X);
    217 }
    218 
    219 int n,m,a[M]={0};
    220 
    221 int main(){
    222     ins(0,0); ins(0,0);
    223     FF::ins(0,0); FF::ins(0,0);
    224     int cas; scanf("%d",&cas);
    225     scanf("%d%d%d",&P,&n,&m); P--; 
    226     for(int i=1;i<=n;i++) scanf("%d",a+i),a[i]--;
    227     
    228     for(int i=1;i<=n+1;i++){
    229         ins(a[i]-a[i-1],i);
    230         FF::ins(a[i]==-1,i);
    231     }
    232     
    233     while(m--){
    234         int op,x,y;
    235         scanf("%d%d%d",&op,&x,&y);
    236         if(op==1){
    237             int F=FF::query(x,y);
    238             if(F) {printf("1
    "); continue;}
    239             int ans=query(x+1,y);
    240             int las=getval(x);
    241             printf("%lld
    ",getans(GCD(las,ans)));
    242         }
    243         if(op==3){
    244             int k; scanf("%d",&k);
    245             updata(x+1,k);
    246             updata(y+2,-k);
    247             FF::updata(x,y);
    248         }
    249         if(op==2){
    250             if(x==y) continue;
    251             int Vl=getval(x-1);
    252             int VR=getval(y);
    253             int Vr=getval(y+1);
    254             setrev(x+1,y);
    255             FF::setrev(x,y);
    256             setval(x,VR-Vl);
    257             
    258             VR=getval(y);
    259             
    260             setval(y+1,Vr-VR);
    261         }
    262     }
    263 }
  • 相关阅读:
    logstash 抓取IIS日志文件写入Elasticsearch
    logstash filter geoip 转换IP为详细地址等内容。
    windows2012 iis配置
    REST接口规范
    windows10后台启动redis
    Docsify生成文档网站
    IDEA类和方法注释自动生成(2019-08-31 21:47写)
    键盘注释
    使用git上传项目解决码云文件次数上传限制(2019-09-25 12:49编写)
    Electron之Hello world(一)
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10646913.html
Copyright © 2020-2023  润新知