BZOJ2243 [SDOI2011]染色

Description

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数nm,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面行每行包含两个整数xy,表示xy之间有一条无向边。

下面行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括ab)都染成颜色c

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括ab)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

Sample Input

6 5

2 2 1 2 1 1

1 2

1 3

2 4

2 5

2 6

Q 3 5

C 2 1 1

Q 3 5

C 5 1 2

Q 3 5

Sample Output

3

1

2

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

Source

第一轮day1

 

 

正解:树链剖分+线段树

解题报告:

  链剖裸题,套个线段树。

  这题唯一难的就在于查询颜色段的时候要考虑跨越查询区间时,要记得去掉重复的部分。合并区间的时候看一下两边区间相接的部分是否是相同颜色,相同的话减掉就可以了。

  线段树维护这一段区间的左端点颜色,右端点颜色,区间不同颜色的和,记得lazy标记。

  这题AC之前WA了两发,第一发是因为没考虑颜色可以为0,第二发是因为没有对于线段树跨越区间情况去重。  

 

  1 //It is made by jump~
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <ctime>
  9 #include <vector>
 10 #include <queue>
 11 #include <map>
 12 #include <set>
 13 #ifdef WIN32   
 14 #define OT "%I64d"
 15 #else
 16 #define OT "%lld"
 17 #endif
 18 using namespace std;
 19 typedef long long LL;
 20 const int MAXN = 100011;
 21 int n,m,ecnt,ans;
 22 int first[MAXN],next[MAXN*2],to[MAXN*2],val[MAXN];
 23 int top[MAXN],size[MAXN],deep[MAXN],son[MAXN],id[MAXN],pre[MAXN],father[MAXN];
 24 char ch[12];
 25 int ql,qr;
 26 
 27 struct node{
 28     int l,r,lazy;
 29     int lc,rc;//左右端点的颜色
 30     int sum;
 31 }a[MAXN*4];
 32 
 33 inline int getint()
 34 {
 35        int w=0,q=0;
 36        char c=getchar();
 37        while((c<'0' || c>'9') && c!='-') c=getchar();
 38        if (c=='-')  q=1, c=getchar();
 39        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
 40        return q ? -w : w;
 41 }
 42 
 43 inline void dfs1(int x,int fa){
 44     size[x]=1;
 45     for(int i=first[x];i;i=next[i]) {
 46     int v=to[i];
 47     if(v==fa)continue;
 48     deep[v]=deep[x]+1; father[v]=x;
 49     dfs1(v,x);
 50     size[x]+=size[v];if(size[v]>size[son[x]]) son[x]=v;
 51     }
 52 }
 53 
 54 inline void dfs2(int x,int fa){
 55     id[x]=++ecnt;pre[ecnt]=x;
 56     if(son[x]) top[son[x]]=top[x],dfs2(son[x],x);
 57     for(int i=first[x];i;i=next[i]) {
 58     int v=to[i];
 59     if(v==fa || v==son[x]) continue;
 60     top[v]=v; dfs2(v,x);
 61     }
 62 }
 63 
 64 inline void build(int root,int l,int r){
 65     a[root].l=l; a[root].r=r; a[root].lazy=-1;//颜色可能为0!!!
 66     if(l==r) {  a[root].sum=1; a[root].lc=a[root].rc=val[pre[l]]; return ; }
 67     int mid=(l+r)/2; int lc=root*2,rc=lc+1;
 68     build(lc,l,mid); build(rc,mid+1,r);
 69     a[root].sum=a[lc].sum+a[rc].sum; a[root].lc=a[lc].lc; a[root].rc=a[rc].rc;
 70     if(!(a[lc].rc^a[rc].lc)) a[root].sum--;
 71 } 
 72 
 73 inline int lca(int x,int y){
 74     int f1=top[x],f2=top[y];
 75     while(f1!=f2) {
 76     if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
 77     x=father[f1]; f1=top[x];
 78     }
 79     if(deep[x]<deep[y]) swap(x,y);
 80     return y;
 81 }
 82 
 83 inline void pushdown(int root){
 84     int lin=a[root].lazy; a[root].lazy=-1;
 85     if(lin==-1 || a[root].l==a[root].r) return ;
 86     int lc=root*2,rc=lc+1;
 87     a[lc].lazy=a[rc].lazy=lin;
 88     a[root].lc=a[root].rc=a[lc].lc=a[lc].rc=a[rc].lc=a[rc].rc=lin;
 89     a[root].sum=a[lc].sum=a[rc].sum=1;
 90 }
 91 
 92 inline void update(int root){
 93     int lc=root*2,rc=lc+1;
 94     a[root].sum=a[lc].sum+a[rc].sum;   
 95     if(!(a[lc].rc^a[rc].lc)) a[root].sum--;
 96     a[root].lc=a[lc].lc; a[root].rc=a[rc].rc;
 97 }
 98 
 99 inline void query(int root,int l,int r){
100     if(ql>qr) return ;
101     pushdown(root);
102     if(ql<=l && r<=qr) {
103     ans+=a[root].sum;
104     return ;
105     }
106     int mid=(l+r)/2; int lc=root*2,rc=lc+1;
107     if(qr<=mid) query(lc,l,mid); 
108     else if(ql>mid) query(rc,mid+1,r); 
109     else{//注意这里也合并一下左右!!!有可能两个端点相等
110     query(lc,l,mid); query(rc,mid+1,r);
111     if(a[lc].rc==a[rc].lc) ans--;
112     }
113 }
114 
115 inline void change(int root,int l,int r,int z){
116     if(ql>qr) return ;
117     pushdown(root);
118     if(ql<=l && r<=qr) {
119     a[root].lazy=z; a[root].lc=a[root].rc=a[root].lazy; a[root].sum=1; return ;
120     }
121     int mid=(l+r)/2; int lc=root*2,rc=lc+1;
122     if(ql<=mid) change(lc,l,mid,z); if(qr>mid) change(rc,mid+1,r,z);
123     update(root);
124 }
125 
126 inline int getcol(int root,int x){
127     pushdown(root);
128     if(a[root].l==a[root].r) return a[root].lc;
129     int mid=(a[root].l+a[root].r)/2; int lc=root*2,rc=lc+1;
130     if(x<=mid) return getcol(lc,x); else return getcol(rc,x);
131 }
132 
133 inline void ask_change(int x,int f,int z){
134     while(top[x]!=top[f]) {
135     ql=id[top[x]]; qr=id[x];
136     change(1,1,n,z);
137     x=father[top[x]];
138     }
139     ql=id[f],qr=id[x],change(1,1,n,z);
140 }
141 
142 inline void ask_sum(int x,int f){
143     while(top[x]!=top[f]) {
144     ql=id[top[x]]; qr=id[x];
145     query(1,1,n);
146     if(getcol(1,id[top[x]])==getcol(1,id[father[top[x]]])) ans--;//判断相接的部分是否相同,跨越轻边的时候统计一下
147     x=father[top[x]];
148     }
149     ql=id[f],qr=id[x],query(1,1,n);
150 }
151 
152 inline void work(){
153     n=getint(); m=getint();
154     for(int i=1;i<=n;i++) val[i]=getint();
155     int x,y;
156     for(int i=1;i<n;i++) {
157     x=getint(); y=getint();
158     next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
159     next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x;
160     }
161     deep[1]=1; dfs1(1,0); ecnt=0; top[1]=1; dfs2(1,0);
162     build(1,1,n); int z,grand;
163     while(m--) {
164     scanf("%s",ch);
165     if(ch[0]=='Q') {
166         x=getint(); y=getint();
167         grand=lca(x,y); ans=0;
168         ask_sum(x,grand); ask_sum(y,grand);
169         printf("%d\n",ans-1);//不管是连续还是不同颜色都是减一即可
170     }
171     else{
172         x=getint(); y=getint(); z=getint();
173         grand=lca(x,y); 
174         ask_change(x,grand,z); ask_change(y,grand,z);
175     }
176     }
177 }
178 
179 int main()
180 {
181   work();
182   return 0;
183 }

 

 

posted @ 2016-07-25 11:01  ljh_2000  阅读(1721)  评论(0编辑  收藏  举报