RT
都把每个操作写了很详细的注释也查不出来……
样例全部输出 1 ,去掉哪个函数都还是锅了,实在不知道哪里写挂了……
#include<bits/stdc++.h>
#define ll long long
#define R read()
using namespace std;
inline ll read() {
ll s=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-')f*=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
s=s*10+ch-'0';
ch=getchar();
}
return s*f;
}
inline void write(ll x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10),x%=10;
putchar('0'+x);
}//Don't use it for CF.
inline void wk(ll x){write(x);putchar(' ');}
inline void we(ll x){write(x);putchar('\n');}
ll n,m,block,l,r,t,ans;//n,m,分块用的block,左坐标,右坐标,时间坐标,当前答案
ll a[200005],b[200005],ton[200005],anser[200005];//原数组,用来反复修改的数组,桶,答案数组
struct prob{//查询
ll l,r,t,id;//左边界,右边界,时间(第几次修改后),该查询原来的编号
friend bool operator < (const prob &x,const prob &y){//重载运算符,用来排序,分块
if(x.l/block==y.l/block){
if(x.r/block==y.r/block)return x.t<y.t;
return x.r<y.r;
}
return x.l<y.l;
}
}ques[200005];
struct tran{//修改
ll id,val,org;//修改第id个数,修改后,修改前
}chan[200005];
void add(ll x){ans+=!ton[x]++;}//区间加入
void del(ll x){ans-=!--ton[x];}//区间删除
void ins(tran x){//正向修改
if(x.id>=l&&x.id<=r)add(x.val),del(x.org);//该修改的位置影响到了当前区间,修改答案
b[x.id]=x.val;//修改(正向)
}
void era(tran x){//反向修改
if(x.id>=l&&x.id<=r)add(x.org),del(x.val);//同上
b[x.id]=x.org;//修改(反向)
}
signed main(){
n=R,m=R,block=sqrt(n);//分块我用的简单的sqrt……不开2/3次应该问题不大吧
for(ll i=1;i<=n;i++)a[i]=R,b[i]=a[i];//原数组和修改用数组
ll cnt=0;//修改操作计数
for(ll i=1;i<=m;i++){
char c=getchar();
ll k;//记录修改操作的位置,用来记录org
if(c=='Q')ques[i-cnt]=(prob){R,R,cnt,i-cnt};//存储查询,R为快读。意为第(i-cnt)个查询的区间为l,r;该查询发生在第cnt次修改后,该查询原为第i-cnt次查询
else chan[++cnt]=(tran){k=R,R,b[k]},b[k]=chan[cnt].val;//存储修改。意为第++cnt个修改的位置是k,修改值为val,修改前的值为b[k],并对b[k]做修改以便后续修改
}
sort(ques+1,ques+m-cnt+1);//分块,排序
l=1,r=0,t=0;
for(ll i=1;i<=n;i++)b[i]=a[i];
for(ll i=1;i<=m-cnt;i++){
while(l<ques[i].l)del(b[l++]);//以下均为莫队常规操作。
while(l>ques[i].r)add(b[--l]);
while(r<ques[i].r)add(b[++r]);
while(r>ques[i].l)del(b[r--]);
while(t<ques[i].t)ins(chan[++t]);
while(t>ques[i].t)era(chan[t--]);
anser[ques[i].id]=ans;//存答案
}
for(ll i=1;i<=m-cnt;i++)we(anser[i]);
return 0;
}