传送门
然而就是我把数颜色的数据加强了一下。。。
数据范围:
n
,
m
≤
200000
,
a
i
≤
1000000
n,m\le200000,a_i\le1000000
n,m≤200000,ai≤1000000
而且还可以强制在线。。。
反正带修莫队是凉掉了。
正解是
b
i
t
bit
bit套主席树。
考虑用把每个位置上颜色出现的上一个位置作为下标插入到主席树中,然后答案就可以差分出来。
再套上
b
i
t
bit
bit就可以处理动态的情况。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int N=1e6+5,M=2e5+5;
int rt[N],n,m,a[N],pre[N],tot=0,mp[N<<1],las[N],idx[N];
set<int>S[N<<1];
typedef set<int>::iterator It;
namespace sgt{
#define lc (son[p][0])
#define rc (son[p][1])
#define mid (l+r>>1)
int siz[M*50],son[M*50][2],cnt=0;
inline int lowbit(const int&x){return x&-x;}
inline void update(int&p,int o,int l,int r,int k,int v){
if(!p)p=++cnt;
lc=son[o][0],rc=son[o][1],siz[p]=siz[o]+v;
if(l==r)return;
k<=mid?update(lc,son[o][0],l,mid,k,v):update(rc,son[o][1],mid+1,r,k,v);
}
inline int query(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return siz[p];
if(qr<=mid)return query(lc,l,mid,ql,qr);
if(ql>mid)return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
inline void update(int p,int k,int v){for(ri i=p;i<=n;i+=lowbit(i))update(rt[i],rt[i],0,n,k,v);}
inline int query(int p,int k){
int ret=0;
for(ri i=p;i;i-=lowbit(i))ret+=query(rt[i],0,n,0,k);
return ret;
}
inline int ask(int l,int r){return query(r,l-1)-query(l-1,l-1);}
#undef lc
#undef rc
#undef mid
}
inline void change(int x,int y){
It it=S[a[x]].lower_bound(x);
++it;
int aa,bb;
aa=*it,bb=pre[*it];
if(aa!=n+1){
sgt::update(aa,bb,-1);
bb=pre[*it]=pre[x];
sgt::update(aa,bb,1);
}
S[a[x]].erase(x);
it=S[y].lower_bound(x);
aa=*it,bb=pre[*it];
if(aa!=n+1){
sgt::update(aa,bb,-1);
pre[*it]=x;
sgt::update(aa,x,1);
}
else bb=*(--it);
sgt::update(x,pre[x],-1);
pre[x]=bb;
sgt::update(x,pre[x],1);
S[y].insert(x);
a[x]=y;
}
struct Qry{int op,a,b;}qry[N];
int main(){
n=read(),m=read();
for(ri i=1,val;i<=n;++i){
a[i]=read();
mp[++tot]=a[i];
}
for(ri i=1;i<=m;++i){
char x=gc();
while(!isalpha(x))x=gc();
qry[i].op=x=='R';
qry[i].a=read(),qry[i].b=read();
if(x=='R')mp[++tot]=qry[i].b;
}
sort(mp+1,mp+tot+1),tot=unique(mp+1,mp+tot+1)-mp-1;
for(ri i=1;i<=tot;++i)idx[mp[i]]=i;
for(ri i=1;i<=tot;++i)S[i].insert(0),S[i].insert(n+1);
for(ri i=1;i<=n;++i){
a[i]=idx[a[i]];
pre[i]=las[a[i]];
sgt::update(i,pre[i],1);
las[a[i]]=i;
S[a[i]].insert(i);
}
for(ri i=1,a,b;i<=m;++i){
if(qry[i].op==1)change(qry[i].a,idx[qry[i].b]);
else cout<<sgt::ask(qry[i].a,qry[i].b)<<'\n';
}
return 0;
}