首页 > 代码库 > bzoj 2243: SDOI2011 染色
bzoj 2243: SDOI2011 染色
最近总是在做树链剖分的题(觉得有必要学一下倍增算法=_=)。这题也是一个树链剖分。维护和找答案的时候注意区间左右端点的颜色就OK了……
上代码:
#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>#include <cmath>#define N 100010#define inf 0x7f7f7f7fusing namespace std;struct sss{ int color, lc, rc; int num, push;}t[N*4];int n, m, color[N], nowplace = 0;int fa[N], deep[N], w[N], top[N], son[N] = {0}, siz[N] = {0};int p[N] = {0}, v[N*2], next[N*2], bnum = 0;void build_tree(int now, int l, int r){ t[now].push = 0; t[now].num = 0; t[now].color = t[now].lc = t[now].rc = 0; if (l == r) return; int mid = (l+r) /2 ; build_tree(now*2, l, mid); build_tree(now*2+1, mid+1, r);}void update(int now){ t[now].num = t[now*2].num + t[now*2+1].num; if (t[now*2].rc == t[now*2+1].lc) t[now].num--; t[now].lc = t[now*2].lc; t[now].rc = t[now*2+1].rc; if (t[now*2].color && t[now*2+1].color == t[now*2].color) t[now].color = t[now*2].color; else t[now].color = 0;}void downdate(int now){ if (!t[now].push) return; t[now*2].push = t[now*2+1].push = 1; t[now].push = 0; t[now*2].color = t[now*2+1].color = t[now].color; t[now*2].lc = t[now*2].rc = t[now*2+1].rc = t[now*2+1].lc = t[now].color; t[now*2].num = t[now*2+1].num = 1;}int findcolor(int now, int l, int r, int place){ if (l == r) return t[now].color; int mid = (l+r) / 2; downdate(now); if (place <= mid) return findcolor(now*2, l, mid, place); else return findcolor(now*2+1, mid+1, r, place);}void make_tree(int now, int l, int r){ if (l == r) { t[now].color = t[now].lc = t[now].rc = 0; t[now].num = 0; t[now].push = 0; return; } int mid = (l+r) / 2; make_tree(now*2, l, mid); make_tree(now*2+1, mid+1, r);}void tchange(int now, int l, int r, int cl, int cr, int cnum){ if (cl <= l && r <= cr) { t[now].color = cnum; t[now].lc = t[now].rc = cnum; t[now].num = 1; t[now].push = 1; return; } int mid = (l+r) / 2; downdate(now); if (cl <= mid) tchange(now*2, l, mid, cl, cr, cnum); if (cr > mid) tchange(now*2+1, mid+1, r, cl, cr, cnum); update(now);}int task(int now, int l, int r, int al, int ar){ if (al <= l && r <= ar) return t[now].num; int mid = (l+r) / 2, ans = 0; downdate(now); if (al <= mid) ans += task(now*2, l, mid, al, ar); if (ar > mid) ans += task(now*2+1, mid+1, r, al, ar); if (al <= mid && ar > mid) if (findcolor(1, 1, n, mid) == findcolor(1, 1, n, mid+1)) ans--; return ans;}void addbian(int x, int y){ bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y; bnum++; next[bnum] = p[y]; p[y] = bnum; v[bnum] = x;}void dfs_1(int now, int fat, int nowdeep){ int k = p[now]; fa[now] = fat; deep[now] = nowdeep; int maxson = 0; siz[now] = 1; while (k) { if (v[k] != fat) { dfs_1(v[k], now, nowdeep+1); siz[now] += siz[v[k]]; if (siz[v[k]] > maxson) { maxson = siz[v[k]]; son[now] = v[k]; } } k = next[k]; }}void dfs_2(int now, int fat, int nowtop){ int k = p[now]; w[now] = ++nowplace; top[now] = nowtop; tchange(1, 1, n, w[now], w[now], color[now]); if (son[now]) dfs_2(son[now], now, nowtop); while (k) { if (v[k] != fat && v[k] != son[now]) dfs_2(v[k], now, v[k]); k = next[k]; }}void change(int u, int v, int changenum){ int f1 = top[u], f2 = top[v]; if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); } if (f1 == f2) { if (u == v) tchange(1, 1, n, w[u], w[u], changenum); else tchange(1, 1, n, min(w[u], w[v]), max(w[u], w[v]), changenum); } else { tchange(1, 1, n, w[f1], w[u], changenum); change(fa[f1], v, changenum); }}int ask(int u, int v){ int f1 = top[u], f2 = top[v], ans = 0; if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); } if (f1 == f2) { if (u == v) return ans+1; else return task(1, 1, n, min(w[u], w[v]), max(w[u], w[v])); } else { ans += task(1, 1, n, w[f1], w[u]); int x = findcolor(1, 1, n, w[f1]), y = findcolor(1, 1, n, w[fa[f1]]); if (x == y) ans --; ans += ask(fa[f1], v); return ans; }}int main(){ scanf("%d%d", &n, &m); build_tree(1, 1, n); for (int i = 1; i <= n; ++i) scanf("%d", &color[i]); for (int i = 1; i < n; ++i) { int x, y; scanf("%d%d", &x, &y); addbian(x, y); } dfs_1(1, 0, 1); dfs_2(1, 0, 1); for (int i = 1; i <= m; ++i) { char s[2]; scanf("%s", s); if (s[0] == ‘C‘) { int a, b, c; scanf("%d%d%d", &a, &b, &c); change(a, b, c); } else { int a, b; scanf("%d%d", &a, &b); printf("%d\n", ask(a, b)); } } return 0;}
bzoj 2243: SDOI2011 染色
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。