BZOJ 2243: [SDOI2011]染色

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 3732  Solved: 1420

Description

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

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

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

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

 

Input

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

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

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

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

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

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

 

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

解题:树链剖分

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxn = 100010;
  4 struct arc {
  5     int to,next;
  6     arc(int x = 0,int y = -1) {
  7         to = x;
  8         next = y;
  9     }
 10 } e[maxn<<1];
 11 struct node {
 12     int lt,rt,lcolor,rcolor,sum,lazy;
 13 } tree[maxn<<2];
 14 int head[maxn],fa[maxn],top[maxn],dep[maxn];
 15 int son[maxn],siz[maxn],loc[maxn];
 16 int clk,tot;
 17 void add(int u,int v) {
 18     e[tot] = arc(v,head[u]);
 19     head[u] = tot++;
 20 }
 21 void FindHeavyEdge(int u,int father,int depth) {
 22     fa[u] = father;
 23     dep[u] = depth;
 24     son[u] = -1;
 25     siz[u] = 1;
 26     for(int i = head[u]; ~i; i = e[i].next) {
 27         if(e[i].to == father) continue;
 28         FindHeavyEdge(e[i].to,u,depth + 1);
 29         siz[u] += siz[e[i].to];
 30         if(son[u] == -1 || siz[e[i].to] > siz[son[u]])
 31             son[u] = e[i].to;
 32     }
 33 }
 34 void ConnectHeavyEdge(int u,int ancestor) {
 35     top[u] = ancestor;
 36     loc[u] = clk++;
 37     if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor);
 38     for(int i = head[u]; ~i; i = e[i].next) {
 39         if(e[i].to == fa[u] || e[i].to == son[u]) continue;
 40         ConnectHeavyEdge(e[i].to,e[i].to);
 41     }
 42 }
 43 inline void pushdown(int v) {
 44     if(tree[v].lazy != -1) {
 45         tree[v<<1].lazy = tree[v].lazy;
 46         tree[v<<1|1].lazy = tree[v].lazy;
 47         tree[v<<1].lcolor = tree[v<<1].rcolor = tree[v].lazy;
 48         tree[v<<1|1].lcolor = tree[v<<1|1].rcolor = tree[v].lazy;
 49         tree[v].lazy = -1;
 50         tree[v<<1].sum = tree[v<<1|1].sum = 1;
 51     }
 52 }
 53 inline void pushup(int v){
 54     tree[v].sum = tree[v<<1].sum + tree[v<<1|1].sum;
 55     if(tree[v<<1].rcolor == tree[v<<1|1].lcolor) tree[v].sum--;
 56     tree[v].lcolor = tree[v<<1].lcolor;
 57     tree[v].rcolor = tree[v<<1|1].rcolor;
 58 }
 59 void build(int lt,int rt,int v) {
 60     tree[v].lt = lt;
 61     tree[v].rt = rt;
 62     tree[v].lazy = -1;
 63     if(lt == rt) {
 64         tree[v].lcolor = tree[v].rcolor = -1;
 65         tree[v].sum = 1;
 66         return;
 67     }
 68     int mid = (lt + rt)>>1;
 69     build(lt,mid,v<<1);
 70     build(mid + 1,rt,v<<1|1);
 71     pushup(v);
 72 }
 73 void update(int lt,int rt,int color,int v) {
 74     if(lt <= tree[v].lt && rt >= tree[v].rt) {
 75         tree[v].lcolor = tree[v].rcolor = color;
 76         tree[v].lazy = color;
 77         tree[v].sum = 1;
 78         return;
 79     }
 80     pushdown(v);
 81     if(lt <= tree[v<<1].rt) update(lt,rt,color,v<<1);
 82     if(rt >= tree[v<<1|1].lt) update(lt,rt,color,v<<1|1);
 83     pushup(v);
 84 }
 85 int query(int lt,int rt,int v) {
 86     if(lt == tree[v].lt && rt == tree[v].rt) return tree[v].sum;
 87     pushdown(v);
 88     if(rt <= tree[v<<1].rt) return query(lt,rt,v<<1);
 89     if(lt >= tree[v<<1|1].lt) return query(lt,rt,v<<1|1);
 90     int tmp = query(lt,tree[v<<1].rt,v<<1) + query(tree[v<<1|1].lt,rt,v<<1|1);
 91     if(tree[v<<1].rcolor == tree[v<<1|1].lcolor) tmp--;
 92     pushup(v);
 93     return tmp;
 94 }
 95 void CHANGE(int u,int v,int color) {
 96     while(top[u] != top[v]) {
 97         if(dep[top[u]] < dep[top[v]]) swap(u,v);
 98         update(loc[top[u]],loc[u],color,1);
 99         u = fa[top[u]];
100     }
101     if(dep[u] > dep[v]) swap(u,v);
102     update(loc[u],loc[v],color,1);
103 }
104 int getColor(int pos,int v){
105     if(tree[v].lt == tree[v].rt) return tree[v].lcolor;
106     pushdown(v);
107     if(pos <= tree[v<<1].rt) return getColor(pos,v<<1);
108     if(pos >= tree[v<<1|1].lt) return getColor(pos,v<<1|1);
109     pushup(v);
110 }
111 int QUERY(int u,int v) {
112     int ret = 0;
113     while(top[u] != top[v]) {
114         if(dep[top[u]] < dep[top[v]]) swap(u,v);
115         ret += query(loc[top[u]],loc[u],1);
116         if(getColor(loc[top[u]],1) == getColor(loc[fa[top[u]]],1)) --ret;
117         u = fa[top[u]];
118     }
119     if(dep[u] > dep[v]) swap(u,v);
120     ret += query(loc[u],loc[v],1);
121     return ret;
122 }
123 int val[maxn],n,m;
124 int main() {
125     int u,v,color;
126     while(~scanf("%d%d",&n,&m)) {
127         memset(head,-1,sizeof head);
128         tot = clk = 0;
129         for(int i = 1; i <= n; ++i) scanf("%d",val + i);
130         for(int i = 1; i < n; ++i) {
131             scanf("%d%d",&u,&v);
132             add(u,v);
133             add(v,u);
134         }
135         FindHeavyEdge(1,0,0);
136         ConnectHeavyEdge(1,1);
137         build(0,clk-1,1);
138         for(int i = 1; i <= n; ++i)
139             update(loc[i],loc[i],val[i],1);
140         char op[10];
141         while(m--) {
142             scanf("%s",op);
143             if(op[0] == 'Q') {
144                 scanf("%d%d",&u,&v);
145                 printf("%d\n",QUERY(u,v));
146             } else if(op[0] == 'C') {
147                 scanf("%d%d%d",&u,&v,&color);
148                 CHANGE(u,v,color);
149             }
150         }
151     }
152     return 0;
153 }
154 /*
155 6 5
156 2 2 1 2 1 1
157 1 2
158 1 3
159 2 4
160 2 5
161 2 6
162 Q 3 5
163 C 2 1 1
164 Q 3 5
165 C 5 1 2
166 Q 3 5
167 */
View Code

 

posted @ 2015-09-29 08:34  狂徒归来  阅读(243)  评论(0编辑  收藏  举报