维护每个位置x的上一个相等的位置pv[x],可以把询问表示成l<=x<=r,pv[x]<l的形式,对一次修改,均摊改变O(1)个pv的取值,因此可以用平衡树预处理出pv的变化,用cdq分治处理查询。
#include<bits/stdc++.h> char buf[3000007],*ptr=buf; const int N=100007; int _(){ int x=0; while(*ptr<48)++ptr; while(*ptr>47)x=x*10+*ptr++-48; return x; } struct itv{ int l; mutable int r,x; bool operator<(const itv&w)const{return l<w.l;} }; typedef std::set<itv>::iterator IT; std::set<itv>c,cs[N*2]; int n,m,v0[N],vs[N*2],vp=0; int os[N][4],pw[N*2],pv[N]; struct P{ int t,x,y,a; bool operator<(const P&w)const{return x<w.x;} }ps[N*10],qs[N*2],pb[N*10]; int px[N],qx[N]; int pp=0,qp=0,now,ans[N]; int bit[N][2],tk=1,c0; void inc(int w,int a){ if(!w)c0+=a; else for(;w<=n;w+=w&-w){ bit[w][0]!=tk?bit[w][0]=tk,bit[w][1]=0:0; bit[w][1]+=a; } } int sum(int w){ int s=c0; for(;w;w-=w&-w){ s+=(bit[w][0]==tk?bit[w][1]:0); } return s; } void clr(){ ++tk,c0=0; } void msort(P*l,P*m,P*r){ P*bp=pb,*p1=l,*p2=m; while(p1!=m&&p2!=r)*bp++=*(p1->x<p2->x?p1:p2)++; while(p1!=m)*bp++=*p1++; while(p2!=r)*bp++=*p2++; memcpy(l,pb,(r-l)*sizeof(P)); } void calc(int L,int R,int lp,int rp,int lq,int rq){ if(L==R){ std::sort(ps+lp,ps+rp); std::sort(qs+lq,qs+rq); return; } int M=(L+R)>>1,mp=px[M],mq=qx[M]; calc(L,M,lp,mp,lq,mq); calc(M+1,R,mp,rp,mq,rq); if(lp<mp&&mq<rq){ clr(); for(int i=mq,j=lp;i<rq;++i){ for(;j<mp&&ps[j].x<=qs[i].x;++j)inc(ps[j].y,ps[j].a); int z; ans[qs[i].t]+=z=sum(qs[i].y)*qs[i].a; } } msort(ps+lp,ps+mp,ps+rp); msort(qs+lq,qs+mq,qs+rq); } void setpv(int w,int v){ if(pv[w]==v)return; ps[pp++]=(P){now,w,pv[w],-1}; pv[w]=v; ps[pp++]=(P){now,w,v,1}; } int getpv(int w,int x){ IT it=cs[w].lower_bound((itv){x}); if(it==cs[w].begin())return 0; --it; return it->r>=x?x-1:it->r; } void setq(int l,int r){ qs[qp++]=(P){now,r,l-1,1}; qs[qp++]=(P){now,l-1,l-1,-1}; } int xs[N],xp,cms[N],cp; void modify(int l,int r,int x){ IT it,it2,del; xp=cp=0; it=c.upper_bound((itv){r});--it; if(it->r>r){ cs[it->x].insert((itv){r+1,it->r}); cs[it->x].find(*it)->r=r; c.insert((itv){r+1,it->r,it->x}); it->r=r; } it=c.upper_bound((itv){l});--it; if(it->l<l){ cs[it->x].insert((itv){l,it->r}); cs[it->x].find(*it)->r=l-1; c.insert((itv){l,it->r,it->x}); it->r=l-1; } for(it=c.find((itv){l});it!=c.end();it2=it,++it,c.erase(it2)){ xs[xp++]=it->l; if(it->l>r)break; cms[cp++]=it->x; cs[it->x].erase(*it); } c.insert((itv){l,r,x}); cs[x].insert((itv){l,r}); for(int i=0;i<xp;++i){ int d=xs[i]-1; if(xs[i]==l)d=getpv(x,xs[i]); else if(xs[i]>r)d=getpv(it->x,xs[i]); setpv(xs[i],d); } cms[cp++]=x; for(int i=0;i<cp;++i){ it=cs[cms[i]].upper_bound((itv){r}); if(it!=cs[cms[i]].end()){ setpv(it->l,getpv(cms[i],it->l)); } } } int main(){ fread(buf,1,sizeof(buf),stdin); n=_();m=_(); for(int i=1;i<=n;++i)vs[vp++]=v0[i]=_(); for(int i=1;i<=m;++i){ os[i][0]=_(); os[i][1]=_(); os[i][2]=_(); if(os[i][0]==1)vs[vp++]=os[i][3]=_(); } std::sort(vs,vs+vp); vp=std::unique(vs,vs+vp)-vs; for(int i=1;i<=n;++i)v0[i]=std::lower_bound(vs,vs+vp,v0[i])-vs; for(int i=1;i<=m;++i)os[i][3]=std::lower_bound(vs,vs+vp,os[i][3])-vs; for(int i=1;i<=n;++i){ cs[v0[i]].insert((itv){i,i}); c.insert((itv){i,i,v0[i]}); pv[i]=pw[v0[i]]; ps[pp++]=(P){0,i,pv[i],1}; pw[v0[i]]=i; } px[0]=pp,qx[0]=qp; for(int i=now=1;i<=m;++now,++i){ if(os[i][0]==1)modify(os[i][1],os[i][2],os[i][3]); else setq(os[i][1],os[i][2]); px[i]=pp,qx[i]=qp; } calc(0,m,0,pp,0,qp); for(int i=1;i<=m;++i)if(os[i][0]==2)printf("%d\n",ans[i]); return 0; }