传送门
解析:
这道题好像以前在BZOJ上做过。
但是因为BZOJ数据较水,所以被我复杂度不对的代码搞过去了。。
真正的排序策略应该是这样的:
块大小设置成
n
2
3
n^{\frac{2}{3}}
n32
左端点块不同就按照左端点块排序。
右端点块不同根据左端点块标号的奇偶性排序。
不然就按照时间戳的顺序排个序。
每次暴力修改时间戳,然后调整块的左右端点。
这样复杂度才是真正的 O ( n 5 3 ) O(n^{\frac{5}{3}}) O(n35)
证明自己用势能分析一下就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline void outint(int a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
inline char getalpha(){
re char c;
while(!isalpha(c=gc()));
return c;
}
cs int N=100005,M=1000006;
int now,ans[N],l=1,r=0,cur;
int pre[N],pos[N],col[N],COL[N],cnt[M],tim[N];
int idxC,qcnt;
int B,block[N],bcnt;
struct Query{
int l,r,tim,id,pre;
friend bool operator<(cs Query &a,cs Query &b){
if(block[a.l]^block[b.l])return block[a.l]<block[b.l];
if(block[a.r]^block[b.r])return (block[a.l]&1)^(a.r>b.r);
return a.pre<b.pre;
}
}q[N];
inline void tim_r(int cur){
if(l<=pos[cur]&&pos[cur]<=r){
--cnt[COL[pos[cur]]];
if(!cnt[COL[pos[cur]]])--now;
}
pre[cur]=COL[pos[cur]];
COL[pos[cur]]=col[cur];
if(l<=pos[cur]&&pos[cur]<=r){
if(!cnt[COL[pos[cur]]])++now;
++cnt[COL[pos[cur]]];
}
}
inline void tim_l(int cur){
if(l<=pos[cur]&&pos[cur]<=r){
--cnt[COL[pos[cur]]];
if(!cnt[COL[pos[cur]]])--now;
}
COL[pos[cur]]=pre[cur];
if(l<=pos[cur]&&pos[cur]<=r){
if(!cnt[COL[pos[cur]]])++now;
++cnt[COL[pos[cur]]];
}
}
inline void tim_adjust(int now){
while(cur<idxC&&tim[cur+1]<=now)tim_r(++cur);
while(cur&&tim[cur]>now)tim_l(cur--);
}
inline void add(int pos){
if(!cnt[COL[pos]])++now;
++cnt[COL[pos]];
}
inline void del(int pos){
--cnt[COL[pos]];
if(!cnt[COL[pos]])--now;
}
int n,m;
signed main(){
n=getint();
m=getint();
B=pow(n,2.0/3.0);
bcnt=1;
for(int re i=1;i<=n;++i){
COL[i]=getint();
block[i]=bcnt;
if(i%B==0)++bcnt;
}
for(int re i=1;i<=m;++i){
switch(getalpha()){
case 'Q':{
q[++qcnt].id=qcnt;
q[qcnt].tim=i;
q[qcnt].l=getint();
q[qcnt].r=getint();
q[qcnt].pre=idxC;
break;
}
case 'R':{
tim[++idxC]=i;
pos[idxC]=getint();
col[idxC]=getint();
break;
}
}
}
sort(q+1,q+qcnt+1);
for(int re i=1;i<=qcnt;++i){
tim_adjust(q[i].tim);
while(r<q[i].r)add(++r);
while(l>q[i].l)add(--l);
while(r>q[i].r)del(r--);
while(l<q[i].l)del(l++);
ans[q[i].id]=now;
}
for(int re i=1;i<=qcnt;++i){
outint(ans[i]);
pc('\n');
}
return 0;
}