傳送門
這道題需要我們在查詢的時候修改內容,但是我們可以對其加一個時間戳,把每次的修改都記錄一下,如果時間晚了就改回去,反之一樣
然後其他的操作就和普通的沒多大區別了,直接上代碼(記得開O2)
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
struct node {
int l,r,time,id;
} t[maxn<<2];
struct date {
int pos,color,last;
} ct[maxn<<2];
int a[maxn],cnt[maxn<<1],ans[maxn],belong[maxn];
int cntq=0,cntt=0;
int cmp(node x,node y) {
return (belong[x.l] ^ belong[y.l]) ? belong[x.l] < belong[y.l] : ((belong[x.r] ^ belong[y.r]) ? belong[x.r]<belong[y.r] : x.time<y.time);
}
inline int read() {
int res = 0;
char c = getchar();
while((c) < '0' || (c) > '9') c = getchar();
while((c) >= '0' && (c) <= '9') res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
return res;
}
int main() {
int n,m;
cin>>n>>m;
int size=pow(n,2.0/3.0);
int bnum=ceil((double)n/size);
for(int i=1; i<=bnum; i++)
for(int j=(i-1)*size+1; j<=i*size; j++) belong[j]=i;
for(int i=1; i<=n; i++)a[i]=read();
for(int i=0; i<m; i++) {
char opt[100];
scanf("%s",opt);
if(opt[0]=='Q') {
t[++cntq].l=read();
t[cntq].r=read();
t[cntq].time=cntt;
t[cntq].id=cntq;
} else if(opt[0]=='R') {
ct[++cntt].pos=read();
ct[cntt].color=read();
}
}
sort(t+1,t+cntq+1,cmp);
int l=1,r=0,time=0,now=0;
for(int i=1; i<=cntq; i++) {
int ql=t[i].l,qr=t[i].r,qt=t[i].time;
while(l<ql)now -= !--cnt[a[l++]];
while(l>ql)now += !cnt[a[--l]]++;
while(r<qr)now += !cnt[a[++r]]++;
while(r>qr)now -= !--cnt[a[r--]];
while(time < qt) {
++time;
if(ql <= ct[time].pos && ct[time].pos <= qr) now -= !--cnt[a[ct[time].pos]] - !cnt[ct[time].color]++;
swap(a[ct[time].pos], ct[time].color);
}
while(time > qt) {
if(ql <= ct[time].pos && ct[time].pos <= qr) now -= !--cnt[a[ct[time].pos]] - !cnt[ct[time].color]++;
swap(a[ct[time].pos], ct[time].color);
--time;
}
ans[t[i].id] = now;
}
for(int i=1; i<=cntq; i++) printf("%d\n",ans[i]);
return 0;
}