(带修莫队题....有点卡常需要调整块的大小....最合适的位置为sz=(n^(2/3)),可通过基本不等式证明,(明天补树套树做法
题解:权值很小,数组可解决(权值过大应该考虑离散化),然后就是基本带修操作
#include <bits/stdc++.h> #define ll long long #define s second #define f first #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=5e4+10; const int NM=1e6+100; using namespace std; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int n,m; int a[MAXN],b[MAXN]; typedef struct node{ int pos,x,y; }node; node d1[MAXN],d2[MAXN]; int p[MAXN],flag[NM]; typedef struct Node{ int l,r,t,id; friend bool operator<(Node aa,Node bb){ if(p[aa.l]==p[bb.l]&&p[aa.r]==p[bb.r]) return aa.t<bb.t; else if(p[aa.l]==p[bb.l]) return p[aa.r]<p[bb.r]; else return p[aa.l]<p[bb.l]; } }Node; Node que[MAXN]; int ans[MAXN],ans1; void join(int l,int r,int pos){ if(l<=d1[pos].pos&&d1[pos].pos<=r){ flag[d1[pos].x]--; if(!flag[d1[pos].x])ans1--; flag[d1[pos].y]++; if(flag[d1[pos].y]==1)ans1++; } a[d1[pos].pos]=d1[pos].y; } void erase(int l,int r,int pos){ if(l<=d2[pos].pos&&d2[pos].pos<=r){ flag[d2[pos].x]--; if(!flag[d2[pos].x])ans1--; flag[d2[pos].y]++; if(flag[d2[pos].y]==1)ans1++; } a[d2[pos].pos]=d2[pos].y; } int main(){ n=read(),m=read();int sz=(int)pow(n,2.0/3); for(int i=1;i<=n;i++)p[i]=(i-1)/sz+1; inc(i,1,n)a[i]=read(),b[i]=a[i]; int t=0,pos,vul;char ch;int cnt=0; for(int i=1;i<=m;i++){ scanf(" %c",&ch); if(ch=='Q'){ que[++cnt].l=read();que[cnt].r=read();que[cnt].id=i;que[cnt].t=t; } else{ t++;pos=read(),vul=read(); d1[t].pos=pos;d1[t].x=b[pos];d1[t].y=vul; d2[t].pos=pos;d2[t].x=vul;d2[t].y=b[pos]; b[pos]=vul; } ans[i]=-1; } sort(que+1,que+cnt+1); int L=1,R=0,T=0;ans1=0; for(int i=1;i<=cnt;i++){ while(que[i].t<T){ erase(L,R,T);T--; } while(que[i].t>T){ T++;join(L,R,T); } while(que[i].l>L){ flag[a[L]]--; if(!flag[a[L]])ans1--; L++; } while(que[i].l<L){ L--;flag[a[L]]++; if(flag[a[L]]==1)ans1++; } while(que[i].r<R){ flag[a[R]]--; if(!flag[a[R]])ans1--; R--; } while(que[i].r>R){ R++;flag[a[R]]++; if(flag[a[R]]==1)ans1++; } ans[que[i].id]=ans1; } for(int i=1;i<=m;i++)if(ans[i]>=0)printf("%d ",ans[i]); return 0; }