2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9961 Solved: 3778
[Submit][Status][Discuss]
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
3
1
2
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
总结:树剖 + 线段树维护, 注意线段树合并的时候需要判断颜色是否相同,颜色相同要减一
#include<bits/stdc++.h> using namespace std; const int maxn = 400005; int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9') {x = x * 10 + ch - 48; ch = getchar();} return x * f; } int n, m, top[maxn], dep[maxn], f[maxn], siz[maxn], a[maxn], sum[maxn], rc[maxn], laz[maxn]; int head[maxn], cnt = 1, son[maxn], wt[maxn], tot = 0, id[maxn], lc[maxn]; char Q[2]; struct Node{ int v, nxt; } G[maxn]; void insert(int u, int v) { G[cnt] = (Node) {v, head[u]}; head[u] = cnt++; } void dfs1(int x, int fa, int deep) { dep[x] = deep; f[x] = fa; int maxson = -1; siz[x] = 1; for (int i = head[x]; i; i = G[i].nxt) { int v = G[i].v; if(v == fa) continue; dfs1(v, x, deep + 1); siz[x] += siz[v]; if(siz[v] > maxson) maxson = siz[v], son[x] = v; } } void dfs2(int x, int topf) { id[x] = ++tot; wt[tot] = a[x]; top[x] = topf; if(son[x] != 0) dfs2(son[x], topf); for (int i = head[x]; i; i = G[i].nxt) { int v = G[i].v; if(v == son[x] || v == f[x]) continue; dfs2(v, v); } } void update(int o, int l, int r) { sum[o] = sum[o << 1] + sum[o << 1 | 1] - (rc[o << 1] == lc[o << 1 | 1]); lc[o] = lc[o << 1], rc[o] = rc[o << 1 | 1]; } void build(int o, int l, int r) { if(l == r) { sum[o] = 1; lc[o] = rc[o] = wt[l]; return; } int mid = (l + r) >> 1; build(o << 1, l, mid); build(o << 1 | 1, mid + 1, r); update(o, l, r); } void pushdown(int o, int l, int r) { if(laz[o]) { laz[o << 1] = laz[o << 1 | 1] = laz[o]; sum[o << 1] = sum[o << 1 | 1] = 1; lc[o << 1] = lc[o << 1 | 1] = rc[o << 1] = rc[o << 1 | 1] = laz[o]; laz[o] = 0; } } int query(int o, int l, int r, int ql, int qr) { if(r < ql || l > qr) return 0; if(ql <= l && r <= qr) return sum[o]; int mid = (l + r) >> 1; pushdown(o, l, r); int res1 = query(o << 1, l, mid, ql, qr); int res2 = query(o << 1 | 1, mid + 1, r, ql, qr); if(res1 && res2) return res1 + res2 - (lc[o << 1 | 1] == rc[o << 1]); else return res1 + res2; } int getcol(int o, int l, int r, int x) { if(l == r) return lc[o]; int mid = (l + r) >> 1; pushdown(o, l, r); if(x <= mid) return getcol(o << 1, l, mid, x); else return getcol(o << 1 | 1, mid + 1, r, x); } int query_rg(int x, int y) { int res = 0; while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); res += query(1, 1, n, id[top[x]], id[x]); if(getcol(1, 1, n, id[f[top[x]]]) == getcol(1, 1, n, id[top[x]])) res--; x = f[top[x]]; } if(dep[x] < dep[y]) swap(x, y); res += query(1, 1, n, id[y], id[x]); return res; } void modify(int o, int l, int r, int ql, int qr, int z) { if(ql <= l && r <= qr) { laz[o] = z; sum[o] = 1; lc[o] = rc[o] = z; return; } int mid = (l + r) >> 1; pushdown(o, l, r); if(ql <= mid) modify(o << 1, l, mid, ql, qr, z); if(qr > mid) modify(o << 1 | 1, mid + 1, r, ql, qr, z); update(o, l, r); } void modify_rg(int x, int y, int z) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); modify(1, 1, n, id[top[x]], id[x], z); x = f[top[x]]; } if(dep[x] < dep[y]) swap(x, y); modify(1, 1, n, id[y], id[x], z); } int main() { n = read(); m = read(); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= n - 1; ++i) { int x, y; x = read(); y = read(); insert(x, y); insert(y, x); } dfs1(1, -1, 0); dfs2(1, 1); build(1, 1, n); while(m--) { int a, b, c; scanf("%s", Q); if(Q[0] == 'Q') a = read(), b = read(), printf("%d\n", query_rg(a, b)); else a = read(), b = read(), c = read(), modify_rg(a, b, c); } }