本文共 3837 字,大约阅读时间需要 12 分钟。
题解里面说得很清楚了。
大约就是单独考虑每个数的贡献,然后看一下每个序列里有多少区间是没有这个数的,乘起来就好了。
为了处理修改我们需要每个值建一棵线段树来搞,但是窝zz了,写了线段树套线段树,比正解多一个log。
一开始想着不调map、set,然后发现特别难写。最后还是调了map……
比赛的时候挂了0没有逆元的坑啊!
#include#include #include #define pii pair#define mpii make_pair#define MN 410000using 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 =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 ,int> ma;map ,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 >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); }}
转载于:https://www.cnblogs.com/Enceladus/p/7115321.html