其他分享
首页 > 其他分享> > [BZOJ 2120]带修主席树 数颜色

[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^6​6​​。 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