1. 程式人生 > >BZOJ_2243 [SDOI2011]染色 【樹鏈剖分+線段樹】

BZOJ_2243 [SDOI2011]染色 【樹鏈剖分+線段樹】

sdoi pre size memory open mes sin urn Language

一  題目

  [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

BZOJ_2243 [SDOI2011]染色 【樹鏈剖分+線段樹】