[BZOJ 2120]带修主席树 数颜色
作者:互联网
B. 数颜色
题目描述
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令:
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
输入格式
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。
第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。
第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
输出格式
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
样例
样例输入
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
样例输出
4
4
3
4
数据范围与提示
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^66。 2016.3.2新加数据两组by Nano_Ape
题目可转化为带修[L,R]内不同数的个数,就用主席树了。 权值主席树维护位置上的数的前驱,在求[L,R]内不同数的个数时就将R树与L-1树作差取<=L-1的数的个数。 修改时考虑对于pos这个位置改为col,会有另两个位置受影响。 一个是以pos为pre的位置,它的pre要变为pre[pos]。 一个是pos后第一个以col为颜色的位置,pre[pos]要变为这个位置的pre,这个位置的pre要变为pos(有点像前向星)。 注意!pos后可能不存在以col为颜色的位置,但前面有可能有col这个颜色!(即1 3 5 2 6,将pos=5的col变为3,后面没有3了,但是它的pre应为2) 所以当pos后不存在以col为颜色的位置时,再向前扫一边,看是否有col这个颜色,找最近的作为pre[pos]. 代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int n,m; 5 int col[N],head[N*10],pre[N],rt[N]; 6 #define lowbit(x) (x&(-x)) 7 struct Chairman_Tree{ 8 struct Tree{ 9 int lch,rch; 10 int size; 11 }node[N*500]; 12 int cnt; 13 void Update(int&x,int l,int r,int pos,int dat){ 14 int k=++cnt; 15 node[k]=node[x]; 16 x=k; 17 node[x].size+=dat; 18 if(l==r)return; 19 int mid=l+r>>1; 20 if(pos<=mid)Update(node[x].lch,l,mid,pos,dat); 21 else Update(node[x].rch,mid+1,r,pos,dat); 22 } 23 void Add(int x,int pos,int dat){ 24 while(x<=n){ 25 Update(rt[x],0,n,pos,dat); 26 x+=lowbit(x); 27 } 28 } 29 int query(int x,int l,int r,int pos){ 30 if(pos>=r)return node[x].size; 31 int mid=l+r>>1; 32 if(pos>mid)return node[node[x].lch].size+query(node[x].rch,mid+1,r,pos); 33 else return query(node[x].lch,l,mid,pos); 34 } 35 }CT; 36 int main(){ 37 //freopen("1.in","r",stdin); 38 scanf("%d%d",&n,&m); 39 for(int i=1;i<=n;++i){ 40 scanf("%d",&col[i]); 41 pre[i]=head[col[i]]; 42 head[col[i]]=i; 43 CT.Add(i,pre[i],1); 44 } 45 int L,R,pos,co,las_la,las_ne,ti_ne; 46 for(int oo=1;oo<=m;++oo){ 47 char ch[5];scanf("%s",ch); 48 if(ch[0]=='Q'){ 49 scanf("%d%d",&L,&R); 50 int ans=0; 51 if(L>R){puts("0");continue;} 52 if(L==R){puts("1");continue;} 53 if(L>n||R>n||L<1||R<1){puts("0");continue;} 54 for(int i=R;i;i-=lowbit(i))ans+=CT.query(rt[i],0,n,L-1); 55 for(int i=L-1;i;i-=lowbit(i))ans-=CT.query(rt[i],0,n,L-1); 56 printf("%d\n",ans); 57 } 58 else{ 59 las_la=0,las_ne=0,ti_ne=0; 60 scanf("%d%d",&pos,&co); 61 if(col[pos]==co){continue;} 62 CT.Add(pos,pre[pos],-1); 63 for(int i=pos+1;i<=n;++i){ 64 if(las_la&&las_ne)break; 65 if(col[i]==col[pos]&&!las_la)las_la=i; 66 if(col[i]==co&&!las_ne)las_ne=i; 67 } 68 if(las_la){ 69 CT.Add(las_la,pre[las_la],-1); 70 CT.Add(las_la,pre[pos],1); 71 pre[las_la]=pre[pos]; 72 } 73 if(las_ne){ 74 CT.Add(las_ne,pre[las_ne],-1); 75 CT.Add(las_ne,pos,1); 76 CT.Add(pos,pre[las_ne],1); 77 pre[pos]=pre[las_ne]; 78 pre[las_ne]=pos; 79 } 80 else{ 81 for(int i=1;i<=n-1;++i) 82 if(col[i]==co)ti_ne=i; 83 CT.Add(pos,ti_ne,1),pre[pos]=ti_ne; 84 } 85 col[pos]=co; 86 } 87 } 88 return 0; 89 }颓代码爽,一直颓代码一直爽
标签:node,2120,return,画笔,int,pos,mid,带修,BZOJ 来源: https://www.cnblogs.com/hzoi2018-xuefeng/p/11110339.html