bzoj4105: [Thu Summer Camp 2015]平方运算
填坑
我不知道怎么算的,但是所有环的LCM数不会超过60
然后用线段树维护这个东西,每个节点记录子树内的循环节
没到循环节的暴力枚举
复杂度是nlogn再乘以循环节长度
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> #define lc (now<<1) #define rc (now<<1|1) #define mid (ql+qr)/2 using namespace std; typedef long long LL; const int _=1e2; const int maxn=1e5+_; const int maxp=1e4+_; const int maxh=62+10; const int mbit=(1<<17)+_; int gcd(int a,int b){if(a==0)return b;return gcd(b%a,a);} int lcm(int a,int b){return a/gcd(a,b)*b;} int nxt[maxp];bool inh[maxp];int tim,v[maxp]; void init(int p) { for(int i=0;i<p;i++)nxt[i]=i*i%p; tim=0; for(int i=0;i<p;i++) if(v[i]==0) { v[i]=++tim; for(int k=nxt[i];;k=nxt[k]) { if(v[k]==tim) { inh[k]=true; for(int u=nxt[k];u!=k;u=nxt[u])inh[u]=true; break; } if(v[k]>0)break; v[k]=tim; } } } //--------------------------------------yu--------------------------------------------------- struct hh { int len,pos,h[maxh]; hh(){} int insert(int d) { if(inh[d]) { len=0;pos=1;h[++len]=d; for(int k=nxt[d];k!=d;k=nxt[k])h[++len]=k; return 0; } return -1; } void merge(hh h1,hh h2) { len=lcm(h1.len,h2.len);pos=1; for(int k=1,i=h1.pos,j=h2.pos;k<=len;k++,i=i%h1.len+1,j=j%h2.len+1) h[k]=h1.h[i]+h2.h[j]; } int ad(int b){pos=(pos+b-1)%len+1;return h[pos];} }; struct trnode{int sum,la;hh h;};int w[maxn]; struct Segtree { trnode tr[2*mbit]; Segtree(){} void update(int now) { tr[now].sum=tr[lc].sum+tr[rc].sum; if(tr[lc].la!=-1&&tr[rc].la!=-1) { tr[now].la=0; tr[now].h.merge(tr[lc].h,tr[rc].h); } else tr[now].la=-1; } void pushdown(int now) { if(tr[now].la<=0)return ; tr[lc].sum=tr[lc].h.ad(tr[now].la),tr[lc].la=(tr[lc].la+tr[now].la-1)%tr[lc].h.len+1; tr[rc].sum=tr[rc].h.ad(tr[now].la),tr[rc].la=(tr[rc].la+tr[now].la-1)%tr[rc].h.len+1; tr[now].la=0; } void bt(int now,int ql,int qr) { if(ql==qr){tr[now].sum=w[ql],tr[now].la=tr[now].h.insert(w[ql]);return ;} bt(lc,ql,mid),bt(rc,mid+1,qr),update(now); } void change(int now,int ql,int qr,int l,int r) { if(ql==l&&qr==r&&tr[now].la!=-1){tr[now].sum=tr[now].h.ad(1);tr[now].la++;return ;} if(ql==qr){tr[now].la=tr[now].h.insert(nxt[tr[now].sum]),tr[now].sum=nxt[tr[now].sum];return ;} pushdown(now); if(r<=mid) change(lc,ql,mid,l,r); else if(mid+1<=l)change(rc,mid+1,qr,l,r); else change(lc,ql,mid,l,mid),change(rc,mid+1,qr,mid+1,r); update(now); } int getsum(int now,int ql,int qr,int l,int r) { if(ql==l&&qr==r)return tr[now].sum; pushdown(now); if(r<=mid) return getsum(lc,ql,mid,l,r); else if(mid+1<=l)return getsum(rc,mid+1,qr,l,r); else return getsum(lc,ql,mid,l,mid)+getsum(rc,mid+1,qr,mid+1,r); } }S; //---------------------------------data structure--------------------------------------------- int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,Q,p; scanf("%d%d%d",&n,&Q,&p); init(p); for(int i=1;i<=n;i++)scanf("%d",&w[i]); S.bt(1,1,n); int op,x,y; while(Q--) { scanf("%d%d%d",&op,&x,&y); if(op==0)S.change(1,1,n,x,y); else printf("%d\n",S.getsum(1,1,n,x,y)); } return 0; }
pain and happy in the cruel world.