[国家集训队2011]数颜色
很久以前写的,但因为拿来出题一直没敢FA题解。。。
这是一份树套树的题解,n,m<=50000应该是可以跑的。
在那份题解里我写了树套树,其实是因为我要来写这道题懒得改了。。。。
首先维护100000颗平衡树,每个平衡树里的点颜色一样,这样可以方便的求出同种颜色的前驱后继和修改
然后树状数组套主席树,修改的话搞出lst值就可以辣
// It is made by XZZ
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<set>
#define il inline
#define rg register
#define vd void
#define sta static
typedef long long ll;
typedef const int& fast;
using namespace std;
il int gi(){
rg int x=0,f=1;rg char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=10000;
int n,m;
namespace Tree{
namespace SGT{
const double alpha=0.7233333;
int root[1000001],id,val[maxn*50],ch[maxn*50][2],siz[maxn*50],cover[maxn*50],b[maxn*50];
bool del[maxn*50];
il int newnode(int _val){val[++id]=_val,ch[id][0]=ch[id][1]=0,siz[id]=cover[id]=1;return id;}
il vd dfs(const int&rt){
if(!rt)return;
dfs(ch[rt][0]);
if(!del[rt])b[++b[0]]=rt;
dfs(ch[rt][1]);
}
il int divide(int l,int r){
if(l>r)return 0;
int mid=(l+r)>>1;
ch[b[mid]][0]=divide(l,mid-1);
ch[b[mid]][1]=divide(mid+1,r);
siz[b[mid]]=siz[ch[b[mid]][0]]+siz[ch[b[mid]][1]]+!del[b[mid]];
cover[b[mid]]=cover[ch[b[mid]][0]]+cover[ch[b[mid]][1]]+1;
return b[mid];
}
il vd rebuild(int&rt){b[0]=0;dfs(rt);rt=divide(1,b[0]);}
il int*_Insert(int&rt,fast num){
if(!rt){rt=newnode(num);return NULL;}
++siz[rt],++cover[rt];
int*ret=_Insert(ch[rt][num>=val[rt]],num);
if(max(cover[ch[rt][0]],cover[ch[rt][1]])>alpha*cover[rt])ret=&rt;
return ret;
}
il vd Insert(fast y,fast x){int*ls=_Insert(root[y],x);if(ls)rebuild(*ls);}
il int Rank(fast y,fast x){
int ret=1,now=root[y];
while(now)
if(x<=val[now])now=ch[now][0];
else ret+=siz[ch[now][0]]+!del[now],now=ch[now][1];
return ret;
}
il vd _Delete(fast y,int k){
int now=root[y];
while(now){
--siz[now];
if(!del[now]&&k==siz[ch[now][0]]+1){del[now]=1;return;}
if(k<=siz[ch[now][0]])now=ch[now][0];
else k-=siz[ch[now][0]]+!del[now],now=ch[now][1];
}
}
il vd Delete(fast y,fast x){
_Delete(y,Rank(y,x));
if(siz[root[y]]<cover[root[y]]*alpha)rebuild(root[y]);
}
}
il int lb(fast x){return x&-x;}
il vd Update(rg int x,fast y){if(!x)return;while(x<=n)SGT::Insert(x,y),x+=lb(x);}
il vd Update_(rg int x,fast y){if(!x)return;while(x<=n)SGT::Delete(x,y),x+=lb(x);}
il int Query(rg int l,rg int r,fast y){
int ret=0;
while(r)ret+=SGT::Rank(r,y+1)-1,r-=lb(r);
--l;while(l)ret-=SGT::Rank(l,y+1)-1,l-=lb(l);
return ret;
}
}
namespace Set FA♂Q{
set<int>st[1000001];
il vd del(fast x,fast y){st[x].erase(st[x].find(y));}
il vd ins(fast x,fast y){st[x].insert(y);}
il pair<int,int>find(fast x,fast y){
set<int>::iterator it=st[x].find(y);
pair<int,int>ret=make_pair(0,0);
if(it!=st[x].begin())--it,ret.first=*it,++it;
++it;if(it!=st[x].end())ret.second=*it;
return ret;
}
}
int num[maxn],__lst[1000001];
int main(){
n=gi();m=gi();
for(rg int i=1;i<=n;++i)num[i]=gi(),Tree::Update(i,__lst[num[i]]),Set::ins(num[i],i),__lst[num[i]]=i;
int x,y;pair<int,int>s;char opt[10];
while(m--){
scanf("%s",opt),x=gi(),y=gi();
if(opt[0]=='Q')printf("%d\n",Tree::Query(x,y,x-1));
else{
s=Set::find(num[x],x);
Tree::Update_(x,s.first),Tree::Update_(s.second,x),Tree::Update(s.second,s.first);
Set::del(num[x],x),Set::ins((num[x]=y),x);
s=Set::find(num[x],x);
Tree::Update_(s.second,s.first),Tree::Update(s.second,x),Tree::Update(x,s.first);
}
}
return 0;
}
博主是蒟蒻,有问题请指出,谢谢!
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。