BZOJ_2243 [SDOI2011]染色 【树链剖分+线段树】
一 题目
二 分析
感觉树链剖分的这些题真的蛮考验码力的,自己的码力还是不够啊!o(╯□╰)o
还是比较常规的树链剖分,但是一定记得这里的线段树在查询的时候一定要考虑链于链相邻的两个点。
一开始自己已经把很多坑都已经注意了,包括颜色可以为0,链的相邻点,但怎么就是不正确,还是要多刷题。
三 AC代码
1 /************************************************************** 2 Problem: 2243 3 User: Dybala21 4 Language: C++ 5 Result: Accepted 6 Time:6652 ms 7 Memory:18580 kb 8 ****************************************************************/ 9 10 #include <bits/stdc++.h> 11 using namespace std; 12 const int MAXN = 1e5 + 15; 13 int n, m; 14 int c[MAXN]; 15 struct Edge 16 { 17 int to, next; 18 }edge[MAXN<<1]; 19 int head[MAXN], tot; 20 int e[MAXN][2]; 21 int fa[MAXN], deep[MAXN], sz[MAXN], son[MAXN]; 22 int p[MAXN], top[MAXN]; 23 int pos; 24 25 void init() 26 { 27 tot = 0, pos = 0; 28 memset(head, -1, sizeof(head)); 29 memset(son, -1, sizeof(son)); 30 } 31 void addedge(int u, int v) 32 { 33 edge[tot].to = v; 34 edge[tot].next = head[u]; 35 head[u] = tot++; 36 } 37 void dfs1(int u, int pre, int d) 38 { 39 fa[u] = pre; 40 sz[u] = 1; 41 deep[u] = d; 42 for(int i = head[u]; i != -1; i = edge[i].next) 43 { 44 int v = edge[i].to; 45 if(v != pre) 46 { 47 dfs1(v, u, d + 1); 48 sz[u] += sz[v]; 49 if(son[u] == -1 || sz[v] > sz[son[u]]) 50 son[u] = v; 51 } 52 } 53 } 54 void dfs2(int u, int sp) 55 { 56 p[u] = ++pos; 57 top[u] = sp; 58 if(son[u] != -1) 59 dfs2(son[u], sp); 60 else 61 return; 62 for(int i = head[u]; i != -1; i = edge[i].next) 63 { 64 int v = edge[i].to; 65 if(v != fa[u] && v != son[u]) 66 dfs2(v, v); 67 } 68 } 69 int lca(int x, int y) 70 { 71 int f1 = top[x], f2 = top[y]; 72 while(f1 != f2) 73 { 74 75 if(deep[f1] < deep[f2]) 76 { 77 swap(f1, f2); 78 swap(x, y); 79 } 80 x = fa[f1]; 81 f1 = top[x]; 82 } 83 if(deep[x] < deep[y]) swap(x, y); 84 return y; 85 } 86 struct Node 87 { 88 int l, r; 89 int lc, rc; 90 int lazy, sum; 91 }segTree[MAXN*3]; 92 void pushdown(int rt) 93 { 94 int tmp = segTree[rt].lazy; 95 segTree[rt].lazy = -1; 96 if(tmp == -1 || segTree[rt].l == segTree[rt].r) 97 return; 98 segTree[rt<<1].lc = segTree[rt<<1].rc = tmp; 99 segTree[rt<<1|1].lc = segTree[rt<<1|1].rc = tmp; 100 segTree[rt<<1].sum = segTree[rt<<1|1].sum = 1; 101 segTree[rt<<1].lazy = segTree[rt<<1|1].lazy = tmp; 102 } 103 void maintain(int rt) 104 { 105 segTree[rt].sum = segTree[rt<<1].sum + segTree[rt<<1|1].sum; 106 if(segTree[rt<<1].rc == segTree[rt<<1|1].lc) 107 segTree[rt].sum--; 108 segTree[rt].lc = segTree[rt<<1].lc; 109 segTree[rt].rc = segTree[rt<<1|1].rc; 110 } 111 void build(int rt, int l, int r) 112 { 113 segTree[rt].l = l; 114 segTree[rt].r = r; 115 segTree[rt].lazy = -1; 116 segTree[rt].sum = 0; 117 if(l == r) 118 return; 119 int mid = (l + r) >> 1; 120 build(rt<<1, l, mid); 121 build(rt<<1|1, mid + 1, r); 122 } 123 void update(int rt, int l, int r, int val) 124 { 125 pushdown(rt); 126 if(segTree[rt].l == l && segTree[rt].r == r) 127 { 128 segTree[rt].lazy = val; 129 segTree[rt].lc = segTree[rt].rc = val; 130 segTree[rt].sum = 1; 131 return; 132 } 133 int mid = (segTree[rt].l + segTree[rt].r) >> 1; 134 if(r <= mid) 135 update(rt<<1, l, r, val); 136 else if(l > mid) 137 update(rt<<1|1, l, r, val); 138 else 139 { 140 update(rt<<1, l, mid, val); 141 update(rt<<1|1, mid+1, r, val); 142 } 143 maintain(rt); 144 } 145 void update(int x, int y, int val) 146 { 147 while(top[x] != top[y]) 148 { 149 if(deep[top[x]] < deep[top[y]]) 150 swap(x, y); 151 update(1, p[top[x]], p[x], val); 152 x = fa[top[x]]; 153 } 154 if(deep[x] < deep[y]) 155 swap(x, y); 156 update(1, p[y], p[x], val); 157 } 158 int query(int rt, int l, int r) 159 { 160 pushdown(rt); 161 if(segTree[rt].l == l && segTree[rt].r == r) 162 return segTree[rt].sum; 163 int mid = (segTree[rt].l + segTree[rt].r) >> 1; 164 int ans = 0; 165 if(r <= mid) 166 ans += query(rt<<1, l, r); 167 else if(l > mid) 168 ans += query(rt<<1|1, l, r); 169 else 170 { 171 ans += query(rt<<1, l, mid); 172 ans += query(rt<<1|1, mid + 1, r); 173 if(segTree[rt<<1].rc == segTree[rt<<1|1].lc) 174 ans--; 175 } 176 return ans; 177 } 178 int find(int rt, int x) 179 { 180 pushdown(rt); 181 if(segTree[rt].l == segTree[rt].r) 182 return segTree[rt].lc; 183 int mid = (segTree[rt].l + segTree[rt].r) >> 1; 184 if(x <= mid) 185 return find(rt<<1, x); 186 else 187 return find(rt<<1|1, x); 188 } 189 int query(int x, int y) 190 { 191 int res = 0; 192 while(top[x] != top[y]) 193 { 194 if(deep[top[x]] < deep[top[y]]) 195 swap(x, y); 196 res += query(1, p[top[x]], p[x]); 197 if(find(1, p[top[x]]) == find(1, p[fa[top[x]]])) 198 res--; 199 x = fa[top[x]]; 200 } 201 if(deep[x] < deep[y]) 202 swap(x, y); 203 res += query(1, p[y], p[x]); 204 return res; 205 } 206 int main() 207 { 208 //freopen("in.txt", "r", stdin); 209 init(); 210 scanf("%d%d", &n, &m); 211 for(int i = 1; i <= n; i++) 212 scanf("%d", &c[i]); 213 for(int i = 0; i < n - 1; i++) 214 { 215 scanf("%d%d", &e[i][0], &e[i][1]); 216 addedge(e[i][0], e[i][1]); 217 addedge(e[i][1], e[i][0]); 218 } 219 dfs1(1, 1, 1); 220 dfs2(1, 1); 221 build(1, 1, pos); 222 for(int i = 1; i <= n; i++) 223 update(1, p[i], p[i], c[i]); 224 char op; 225 int a, b, val; 226 for(int i = 0; i < m; i++) 227 { 228 scanf(" %c %d %d", &op, &a, &b); 229 if(op == 'Q') 230 { 231 printf("%d\n", query(a, b)); 232 } 233 else 234 { 235 scanf("%d", &val); 236 update(a, b, val); 237 } 238 } 239 return 0; 240 } 241