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,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“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
解题:树链剖分
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 */
夜空中最亮的星,照亮我前行