题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
题意:
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
思路:
权值在点上的树链剖分+线段树成段更新+线段树成段询问。
维护颜色端的数量方法:
如果左儿子区间的最右端颜色与右儿子区间的最左端区间相同。
sum[rt] = sum[rt<<1]+sum[rt<<1|1] - 1;
否则sum[rt] = sum[rt<<1]+sum[rt<<1|1];
树链剖分部分也进行相应维护。
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <cstdio> 5 #include <vector> 6 using namespace std; 7 int n, q; 8 #define maxn 100010 9 #define lson l, m, rt<<1 10 #define rson m+1, r, rt<<1|1 11 int siz[maxn], top[maxn], fa[maxn], son[maxn], dep[maxn]; 12 int w[maxn], fw[maxn]; 13 int A[maxn]; 14 vector <int> mp[maxn]; 15 int pos; 16 int Left, Right; 17 int sum[maxn<<2], cl[maxn<<2], cr[maxn<<2], col[maxn<<2]; 18 void PushUp(int rt) 19 { 20 if(cr[rt<<1] == cl[rt<<1|1]) sum[rt] = sum[rt<<1] + sum[rt<<1|1] - 1; 21 else sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 22 cl[rt] = cl[rt<<1]; 23 cr[rt] = cr[rt<<1|1]; 24 } 25 void PushDown(int rt, int m) 26 { 27 if(col[rt] >= 0) 28 { 29 col[rt<<1] = col[rt<<1|1] = col[rt]; 30 sum[rt<<1] = sum[rt<<1|1] = 1; 31 cl[rt<<1] = cl[rt<<1|1] = cr[rt<<1] = cr[rt<<1|1] = cl[rt]; 32 col[rt] = -1; 33 } 34 } 35 void build(int l, int r, int rt) 36 { 37 col[rt] = -1; 38 if(l == r) 39 { 40 cl[rt] = cr[rt] = A[fw[l]]; 41 sum[rt] = 1; 42 return; 43 } 44 int m = (l+r)>>1; 45 build(lson); 46 build(rson); 47 PushUp(rt); 48 } 49 void update(int L, int R, int c, int l, int r, int rt) 50 { 51 if(L <= l && R >= r) 52 { 53 col[rt] = c; sum[rt] = 1; cl[rt] = c; cr[rt] = c; 54 return; 55 } 56 PushDown(rt, r-l+1); 57 int m = (l+r)>>1; 58 if(L <= m) update(L, R, c, lson); 59 if(R > m) update(L, R, c, rson); 60 PushUp(rt); 61 } 62 int query(int L, int R, int l, int r, int rt) 63 { 64 if(l == L) Left = cl[rt]; 65 if(r == R) Right = cr[rt]; 66 if(L <= l && R >= r) 67 { 68 return sum[rt]; 69 } 70 PushDown(rt, r-l+1); 71 int m = (l+r)>>1; 72 int ret = 0; 73 //合并线段树 这里也要修改! 74 if(R <= m) return query(L, R, lson); 75 else if(L > m) return query(L, R, rson); 76 else 77 { 78 ret = query(L,R,lson) + query(L, R, rson); 79 if(cl[rt<<1|1] == cr[rt<<1]) ret --; 80 return ret; 81 } 82 //if(L <= m) ret += query(L, R, lson); 83 //if(R > m) ret += query(L, R, rson); 84 } 85 int dfs1(int u, int pre, int deep) 86 { 87 siz[u] = 1; dep[u] = deep; fa[u] = pre; 88 int mmax = 0; 89 for(int i = 0; i < mp[u].size(); i++) 90 { 91 if(mp[u][i] != pre) 92 { 93 int temp = dfs1(mp[u][i], u, deep+1); 94 siz[u] += temp; 95 if(son[u] == -1 || temp >= mmax) 96 { 97 son[u] = mp[u][i]; 98 mmax = temp; 99 } 100 } 101 } 102 return siz[u]; 103 } 104 void dfs2(int u, int val) 105 { 106 top[u] = val; 107 if(son[u] != -1) 108 { 109 w[u] = ++pos; 110 fw[w[u]] = u; 111 dfs2(son[u], val); 112 } 113 else if(son[u] == -1) 114 { 115 w[u] = ++pos; 116 fw[w[u]] = u; 117 return; 118 } 119 for(int i = 0; i < mp[u].size(); i++) 120 { 121 if(mp[u][i] != son[u] && mp[u][i] != fa[u]) dfs2(mp[u][i], mp[u][i]); 122 } 123 } 124 int find(int u, int v) 125 { 126 int mark1 = -1, mark2 = -1; 127 int f1 = top[u], f2 = top[v]; 128 int temp = 0; int precolor = -1; 129 while(f1 != f2) 130 { 131 if(dep[f1] < dep[f2]) //规定f1更深 132 { 133 swap(f1, f2); 134 swap(u, v); 135 swap(mark1, mark2); //交替 136 } 137 temp += query(w[f1], w[u], 1, pos, 1); 138 if(Right == mark1) temp --; 139 mark1 = Left; 140 u = fa[f1]; f1 = top[u]; 141 } 142 if(dep[u] < dep[v]) //规定u更深 143 { 144 swap(u, v); 145 swap(mark1, mark2); 146 } 147 temp += query(w[v], w[u], 1, pos, 1); 148 if(Right == mark1) temp--; 149 if(Left == mark2) temp--; 150 return temp; 151 } 152 void UPDATE(int u, int v, int color) 153 { 154 int f1 = top[u], f2 = top[v]; 155 while(f1 != f2) 156 { 157 if(dep[f1] < dep[f2]) 158 { 159 swap(f1, f2); 160 swap(u, v); 161 } 162 update(w[f1], w[u], color, 1, pos, 1); 163 u = fa[f1]; f1 = top[u]; 164 } 165 if(dep[u] > dep[v]) swap(u, v); 166 update(w[u], w[v], color, 1, pos, 1); 167 } 168 int main() 169 { 170 //freopen("in.txt", "r", stdin); 171 while(~scanf("%d%d", &n, &q)) 172 { 173 for(int i = 1; i <= n; i++) mp[i].clear(); 174 pos = 0; 175 memset(son, -1, sizeof(son)); 176 for(int i = 1; i <= n; i++) scanf("%d", &A[i]); 177 for(int i = 1; i <= n-1; i++) 178 { 179 int a, b; scanf("%d%d", &a, &b); 180 mp[a].push_back(b); 181 mp[b].push_back(a); 182 } 183 dfs1(1, -1, 1); 184 dfs2(1, 1); 185 build(1, pos, 1); 186 187 char op[5]; 188 while(q--) 189 { 190 scanf("%s", op); 191 int a, b, c; 192 if(op[0] == 'Q') 193 { 194 scanf("%d%d", &a, &b); 195 printf("%d ", find(a, b)); 196 } 197 else if(op[0] == 'C') 198 { 199 scanf("%d%d%d", &a, &b, &c); 200 UPDATE(a, b, c); 201 } 202 } 203 } 204 return 0; 205 }