_bzoj2243 [SDOI2011]染色【树链剖分】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
裸的树链剖分,最开始我保存一个线段树节点的color值时(若有多种颜色则为-1),不小心使“若其两个子节点color相等,则该节点color值为其儿子的color,并把这个节点内颜色个数设为1”,这是致命的错误——万一两个儿子color都为-1呢?
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> const int maxn = 100005, maxm = 100005; int n, m, ini_c[maxn], t1, t2, t3, root; int head[maxn], to[maxn << 1], next[maxn << 1], lb; int fa[maxn], heavy[maxn], top[maxn], siz[maxn], dep[maxn], id[maxn], a[maxn], cnt; char opr; struct Node { int ql, qr, c, num, lc, rc; } tree[maxn << 2]; inline void ist(int aa, int ss) { to[lb] = ss; next[lb] = head[aa]; head[aa] = lb; ++lb; } void dfs1(int r, int dp) { dep[r] = dp; siz[r] = 1; if (r == 6671) { ++r; --r; } for (int j = head[r]; j != -1; j = next[j]) { if (to[j] != fa[r]) { fa[to[j]] = r; dfs1(to[j], dp + 1); siz[r] += siz[to[j]]; if (siz[to[j]] > siz[heavy[r]]) { heavy[r] = to[j]; } } } } void dfs2(int r, int tp) { if (!r) { return; } id[r] = ++cnt; a[cnt] = ini_c[r]; top[r] = tp; dfs2(heavy[r], tp); for (int j = head[r]; j != -1; j = next[j]) { if (to[j] != fa[r] && to[j] != heavy[r]) { dfs2(to[j], to[j]); } } } void make_tree(int p, int left, int right) { tree[p].ql = left; tree[p].qr = right; if (left == right) { tree[p].c = tree[p].lc = tree[p].rc = a[left]; tree[p].num = 1; return; } int mid = (left + right) >> 1; make_tree(p << 1, left, mid); make_tree(p << 1 | 1, mid + 1, right); if (tree[p << 1].c == tree[p << 1 | 1].c && tree[p << 1].c != -1) { tree[p].c = tree[p].lc = tree[p].rc = tree[p << 1].c; tree[p].num = 1; } else { tree[p].c = -1; tree[p].lc = tree[p << 1].lc; tree[p].rc = tree[p << 1 | 1].rc; tree[p].num = tree[p << 1].num + tree[p << 1 | 1].num; if (tree[p << 1].rc == tree[p << 1 | 1].lc) { --tree[p].num; } } } void upd(int p, int left, int right, int c) { if (tree[p].ql == left && tree[p].qr == right) { tree[p].c = tree[p].lc = tree[p].rc = c; tree[p].num = 1; return; } if (tree[p].c >= 0) { if (tree[p].c == c) { return; } tree[p << 1].c = tree[p << 1 | 1].c = tree[p].c; tree[p << 1].lc = tree[p << 1].rc = tree[p].c; tree[p << 1 | 1].lc = tree[p << 1 | 1].rc = tree[p].c; tree[p << 1].num = tree[p << 1 | 1].num = 1; tree[p].c = -1; } int mid = (tree[p].ql + tree[p].qr) >> 1; if (right <= mid) { upd(p << 1, left, right, c); } else if (left > mid) { upd(p << 1 | 1, left, right, c); } else { upd(p << 1, left, mid, c); upd(p << 1 | 1, mid + 1, right, c); } tree[p].c = -1; tree[p].lc = tree[p << 1].lc; tree[p].rc = tree[p << 1 | 1].rc; tree[p].num = tree[p << 1].num + tree[p << 1 | 1].num; if (tree[p << 1].rc == tree[p << 1 | 1].lc) { --tree[p].num; } } int qry(int p, int left, int right, int & lc, int & rc) { if (tree[p].ql == left && tree[p].qr == right) { lc = tree[p].lc; rc = tree[p].rc; return tree[p].num; } if (tree[p].c >= 0) { lc = rc = tree[p].c; return 1; } int mid = (tree[p].ql + tree[p].qr) >> 1; if (right <= mid) { return qry(p << 1, left, right, lc, rc); } else if (left > mid) { return qry(p << 1 | 1, left, right, lc, rc); } else { int tlc, trc, rt1, rt2; rt1 = qry(p << 1, left, mid, lc, trc); rt2 = qry(p << 1 | 1, mid + 1, right, tlc, rc); return rt1 + rt2 - (trc == tlc? 1: 0); } } inline void C(int u, int v, int c) { while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) { std::swap(u, v); } upd(1, id[top[u]], id[u], c); u = fa[top[u]]; } if (dep[u] < dep[v]) { std::swap(u, v); } upd(1, id[v], id[u], c); } inline int Q(int u, int v) { int rt = 0; int u_lc1 = -666, u_rc1 = -666, u_lc2 = -666, u_rc2 = -666; int v_lc1 = -666, v_rc1 = -666, v_lc2 = -666, v_rc2 = -666; while (top[u] != top[v]) { if (dep[top[u]] > dep[top[v]]) { rt += qry(1, id[top[u]], id[u], u_lc2, u_rc2); if (u_rc2 == u_lc1) { --rt; } u_lc1 = u_lc2; u_rc1 = u_rc2; u = fa[top[u]]; } else { rt += qry(1, id[top[v]], id[v], v_lc2, v_rc2); if (v_rc2 == v_lc1) { --rt; } v_lc1 = v_lc2; v_rc1 = v_rc2; v = fa[top[v]]; } } if (dep[u] > dep[v]) { rt += qry(1, id[v], id[u], u_lc2, u_rc2); if (u_rc2 == u_lc1) { --rt; } if (u_lc2 == v_lc1) { --rt; } } else { rt += qry(1, id[u], id[v], v_lc2, v_rc2); if (v_rc2 == v_lc1) { --rt; } if (v_lc2 == u_lc1) { --rt; } } return rt; } int main(void) { //freopen("paint.in", "r", stdin); //freopen("paint.out", "w", stdout); memset(head, -1, sizeof head); memset(next, -1, sizeof next); unsigned seed; scanf("%d%d", &n, &m); seed += n + m; for (int i = 1; i <= n; ++i) { scanf("%d", ini_c + i); seed += ini_c[i]; } for (int i = 1; i < n; ++i) { scanf("%d%d", &t1, &t2); ist(t1, t2); ist(t2, t1); seed += t1; } srand(seed); root = rand() % n + 1; //root = 1; dfs1(root, 0); dfs2(root, root); make_tree(1, 1, n); while (m--) { while ((opr = getchar()) < 'A'); if (opr == 'C') { scanf("%d%d%d", &t1, &t2, &t3); C(t1, t2, t3); } else { scanf("%d%d", &t1, &t2); printf("%d\n", Q(t1, t2)); } } return 0; }