傳送門node
好吧我是不太會複雜度分析……c++
咱們對於每種顏色用一個數據結構維護(比方說線段樹或者平衡樹,代碼裏寫的平衡樹),那麼區間詢問很容易就能夠解決了數據結構
因此如今的問題是區間修改,若是區間顏色相等直接\(O(\log n)\)修改就行了,不然的話,一個很暴力的思路是把區間分紅若干段顏色相等的部分,每個部分都直接\(O(\log n)\)修改ide
乍看這樣是\(gg\)的,可是咱們仔細觀察一下,每一次修改的時候只有相鄰兩段顏色不一樣的時候會貢獻\(O(\log n)\)的複雜度,而初始時段數是\(O(n)\)的,每一次修改的時候增長的段數是常數,因此總的複雜度是\(O((n+m)\log n)\)this
ps:由於修改的時候要暴力跳區間須要資瓷查詢某個點的顏色因此寫了個珂朵莉樹spa
pps:雖說起來很簡單可是調起來很是麻煩……code
//minamoto #include<bits/stdc++.h> #define R register #define inline __inline__ __attribute__((always_inline)) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){ R int res,f=1;R char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } char sr[1<<21],z[20];int K=-1,Z=0; inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;} void print(R int x){ if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++K]=z[Z],--Z);sr[++K]='\n'; } inline char getop(){R char ch;while((ch=getc())>'Z'||ch<'A');return ch;} unsigned int aaa=19260817; inline unsigned int rd(){aaa^=aaa>>15,aaa+=aaa<<12,aaa^=aaa>>3;return aaa;} const int N=5e5+5; struct node;typedef node* ptr; struct node{ ptr lc,rc;int v,sz;unsigned int pr; inline ptr init(R int val){return v=val,sz=1,pr=rd(),this;} inline ptr upd(){return sz=lc->sz+rc->sz+1,this;} }e[N],*pp=e,*pl,*pr;map<int,ptr>rt; inline ptr newnode(R int v){return ++pp,pp->lc=pp->rc=e,pp->init(v);} void split(ptr p,int k,ptr &s,ptr &t){ if(p==e)return s=t=e,void(); if(p->v<=k)s=p,split(p->rc,k,p->rc,t); else t=p,split(p->lc,k,s,p->lc); p->upd(); } ptr merge(ptr s,ptr t){ if(s==e)return t;if(t==e)return s; if(s->pr<t->pr)return s->rc=merge(s->rc,t),s->upd(); return t->lc=merge(s,t->lc),t->upd(); } int n,m,lasans,a[N]; struct zz{ int l,r;mutable int v; inline zz(R int li,R int ri=0,R int vi=0):l(li),r(ri),v(vi){} inline bool operator <(const zz &b)const{return l<b.l;} };set<zz>s;typedef set<zz>::iterator IT; IT split(int pos){ IT it=s.lower_bound(zz(pos)); if(it!=s.end()&&it->l==pos)return it; --it;int l=it->l,r=it->r,v=it->v; s.erase(it),s.insert(zz(l,pos-1,v)); return s.insert(zz(pos,r,v)).first; } void update(int l,int r,int v){ IT itr=split(r+1),itl=split(l); s.erase(itl,itr),s.insert(zz(l,r,v)); } int ask(int pos){ IT it=s.lower_bound(zz(pos)); if(it==s.end()||it->l!=pos)--it; return it->v; } int Kth(ptr p,int k){ if(p->lc->sz==k-1)return p->v; if(p->lc->sz>=k)return Kth(p->lc,k); return Kth(p->rc,k-p->lc->sz-1); } int query(ptr &rt,int l,int r,int k){ ptr s,t,p,q; split(rt,l-1,s,t),split(t,r,p,q); int now=p->sz>=k?Kth(p,k):0; return rt=merge(s,merge(p,q)),now; } void divide(ptr p,int k,int r,ptr &s,ptr &t){ if(p==e)return s=t=e,void(); if(p->lc->sz+k==p->v&&p->v<=r)s=p,divide(p->rc,k+p->lc->sz+1,r,p->rc,t); else t=p,divide(p->lc,k,r,s,p->lc); p->upd(); } int change(ptr &p,int k,int r){ ptr s,t,f,g;int now; split(p,k-1,f,g),divide(g,k,r,s,t); now=Kth(s,s->sz),p=merge(f,t),pl=merge(pl,s); return now+1; } int main(){ // freopen("gold1.in","r",stdin); n=read(),m=read(),lasans=0,e->lc=e->rc=e; fp(i,1,n){ a[i]=read();if(rt[a[i]]==NULL)rt[a[i]]=e; rt[a[i]]=merge(rt[a[i]],newnode(i)); s.insert(zz(i,i,a[i])); } for(int op,l,r,v,k,tl,tr,c;m;--m){ op=getop(),l=read()^lasans,r=read()^lasans; if(op=='M'){ v=read()^lasans,tl=l,tr=r;if(rt[v]==NULL)rt[v]=e; split(rt[v],l-1,pl,pr),split(pr,r,rt[v],pr); while(tl<=tr)c=ask(tl),tl=change(rt[c],tl,r); rt[v]=merge(pl,pr); update(l,r,v); }else{ k=read()^lasans,v=read()^lasans;if(rt[v]==NULL)rt[v]=e; print(lasans=query(rt[v],l,r,k)); } } return Ot(),0; }