LibreOJ β Round #2 E. 数论只会 GCD
题解里面说得很清楚了。
大约就是单独考虑每个数的贡献,然后看一下每个序列里有多少区间是没有这个数的,乘起来就好了。
为了处理修改我们需要每个值建一棵线段树来搞,但是窝zz了,写了线段树套线段树,比正解多一个log。
一开始想着不调map、set,然后发现特别难写。最后还是调了map……
比赛的时候挂了0没有逆元的坑啊!
#include<map> #include<cstdio> #include<algorithm> #define pii pair #define mpii make_pair #define MN 410000 using namespace std; int read_p,read_ca,read_f; inline int read(){ read_p=0;read_ca=getchar();read_f=1; while(read_ca<'0'||read_ca>'9') {if (read_ca=='-') read_f=-1;read_ca=getchar();} while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p*read_f; } const int MOD=19260817; struct na{int p,*st;}Y[MN<<1]; bool operator < (na a,na b){return a.p<b.p;} inline void M(int &x){while(x>=MOD)x-=MOD;while(x<0)x+=MOD;} int n,m,L[MN],a[MN],ro[MN],RO[MN*40],ls[MN*40],rs[MN*40],LS[MN*100],RS[MN*100],S[MN*100],NUM,x[MN],y[MN],z[MN],T=0,num=0,_num=0,mmh[MN],MMH=1,t[MN],w[MN],ze[MN]; void ADD(int &p,int l,int r,int pos,int v){ if (!p) p=++_num;S[p]+=v; if (l==r) return; int mid=l+r>>1; if (pos<=mid) ADD(LS[p],l,mid,pos,v);else ADD(RS[p],mid+1,r,pos,v); } void add(int &p,int l,int r,int pos,int x,int v){ if (!p) p=++num;ADD(RO[p],1,T,x,v); if (l==r) return; int mid=l+r>>1; if (pos<=mid) add(ls[p],l,mid,pos,x,v);else add(rs[p],mid+1,r,pos,x,v); } int ASK(int p,int l,int r,int k){ if (!p) return 0; if (l==r) return S[p]; int mid=l+r>>1; return k<=mid?ASK(LS[p],l,mid,k):ASK(RS[p],mid+1,r,k); } int p_ask(int p,int l,int r,int pos,int x){ if (ASK(RO[p],1,T,x)==0) return -1; if (pos<=l) return -1; if (l==r) return l; int mid=l+r>>1; int w=p_ask(rs[p],mid+1,r,pos,x); if (w!=-1) return w; return p_ask(ls[p],l,mid,pos,x); } int s_ask(int p,int l,int r,int pos,int x){ if (ASK(RO[p],1,T,x)==0) return -1; if (pos>=r) return -1; if (l==r) return l; int mid=l+r>>1; int w=s_ask(ls[p],l,mid,pos,x); if (w!=-1) return w; return s_ask(rs[p],mid+1,r,pos,x); } inline int mi(int x,int y){ int mmh=1; while (y){ if (y&1) mmh=1LL*mmh*x%MOD; x=1LL*x*x%MOD;y>>=1; } return mmh; } map<pii<int,int>,int> ma; map<pii<int,int>,int>::iterator it; inline void del(int x,int v){ if(!ze[v])M(MMH+=mmh[v]); if (ma.find(mpii(x,v))==ma.end()) ma[mpii(x,v)]=1LL*(L[x]-L[x-1])*(L[x]-L[x-1]+1)/2%MOD; if (!ma[mpii(x,v)]) ze[v]--;else mmh[v]=1LL*mmh[v]*mi(ma[mpii(x,v)],MOD-2)%MOD; } inline void add(int x,int v){if (!ma[mpii(x,v)]) ze[v]++;else mmh[v]=1LL*mmh[v]*ma[mpii(x,v)]%MOD;if(!ze[v])M(MMH-=mmh[v]);} int main(){ n=read();m=read(); for (int i=1;i<=n;i++) L[i]=L[i-1]+read(); for (int i=1;i<=n;i++){ for (int j=L[i-1];j<L[i];j++) Y[++NUM].p=a[j]=read(),Y[NUM].st=&a[j]; MMH=1LL*(L[i]-L[i-1])*(L[i]-L[i-1]+1)/2%MOD*MMH%MOD; } for (int i=1;i<=m;i++) x[i]=read(),y[i]=read(),Y[++NUM].p=z[i]=read(),Y[NUM].st=&z[i]; sort(Y+1,Y+1+NUM); for (int i=1;i<=NUM;i++) T+=i==1||Y[i].p!=Y[i-1].p,*Y[i].st=T; for (int i=1;i<=T;i++) mmh[i]=MMH,ze[i]=0; MMH=1LL*MMH*T%MOD; for (int i=1;i<=n;i++) for (int j=L[i-1];j<L[i];j++)add(ro[i],1,L[i]-L[i-1],j-L[i-1]+1,a[j],1); for (int i=1;i<=n;i++){ for (int j=L[i-1];j<L[i];j++) if (!t[a[j]]) w[j]=(1LL*(j-L[i-1]+1)*(j-L[i-1])>>1)%MOD,t[a[j]]=j+1;else w[j]=((1LL*(j+1-t[a[j]])*(j-t[a[j]])>>1)+w[t[a[j]]-1])%MOD,t[a[j]]=j+1; int s=mi(1LL*(L[i]-L[i-1])*(L[i]-L[i-1]+1)/2%MOD,MOD-2); for (int j=L[i]-1;j>=L[i-1];j--) if (t[a[j]]){ M(w[j]+=1LL*(L[i]-t[a[j]]+1)*(L[i]-t[a[j]])/2%MOD); mmh[a[j]]=1LL*mmh[a[j]]*s%MOD; if (!w[j]) ze[a[j]]++;else mmh[a[j]]=1LL*mmh[a[j]]*w[j]%MOD; ma[mpii(i,a[j])]=w[j]; t[a[j]]=0; } } for (int i=1;i<=T;i++) if (!ze[i]) M(MMH-=mmh[i]); printf("%d\n",MMH); for (int i=1;i<=m;i++){ int pos=L[x[i]-1]+y[i]-1; del(x[i],a[pos]);del(x[i],z[i]); int l=p_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],a[pos]),r=s_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],a[pos]); if (l==-1) l=0;if (r==-1) r=L[x[i]]-L[x[i]-1]+1; it=ma.find(mpii(x[i],a[pos])); M(it->second+=1LL*(r-y[i])*(y[i]-l)%MOD); l=p_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],z[i]),r=s_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],z[i]); if (l==-1) l=0;if (r==-1) r=L[x[i]]-L[x[i]-1]+1; it=ma.find(mpii(x[i],z[i])); M(it->second-=1LL*(r-y[i])*(y[i]-l)%MOD); add(x[i],a[pos]);add(x[i],z[i]); add(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],a[pos],-1); add(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],z[i],1);a[pos]=z[i]; printf("%d\n",MMH); } }