题意:
给出一个无根树和树上每一个结点的初始颜色。
然后进行m次操作;
C:将x到y的路径全部点染成某个颜色;
Q:查询x到y的路径上经过多少个颜色块;
n,m<=10^5;
题解:
挺裸的树链剖分,改动的时候要用延迟标记维护。
可是注意颜色可能为0,所以我单独开了一个bool的数组维护是否有标记;
在合并两个区间的时候要推断两个端点的颜色是否同样;
假设同样要将端点合并,也就是答案-1;
在树链间切换的时候也是要查一下端点;
然后我就WA了!
之后查啊查。查啊查。
。
。
发现我模板敲错了!我还认为那是对的。。。
和曾经的代码对照才发现不正确啊啊啊啊
就是在类似LCA的过程中交换x,y推断的是deep[top[x]]<deep[top[y]]。
我写成了deep[x]<deep[y];
发现博客里没有树剖就写一发传上来以后当模板抄抄= =。
代码:
#include<vector> #include<math.h> #include<stdio.h> #include<string.h> #include<algorithm> #define N 110000 #define lson l,mid,no<<1 #define rson mid+1,r,no<<1|1 using namespace std; vector<int>to[N]; int a[N], fa[N], ch[N], size[N], top[N], deep[N]; int p[N], rank[N], cov[N << 2], L[N << 2], R[N << 2], sum[N << 2], n, tot; bool is[N << 2]; char str[10]; void dfs1(int x, int d, int pre) { deep[x] = d, fa[x] = pre, size[x] = 1; int i, y; for (i = 0; i < to[x].size(); i++) { if ((y = to[x][i]) != pre) { dfs1(y, d + 1, x); size[x] += size[y]; if (size[y]>size[ch[x]]) ch[x] = y; } } } void dfs2(int x, int t) { top[x] = t; p[x] = ++tot; rank[tot] = x; if (ch[x]) dfs2(ch[x], t); int i, y; for (i = 0; i < to[x].size(); i++) { y = to[x][i]; if (y != fa[x] && y != ch[x]) dfs2(y, y); } } void Pushup(int no) { L[no] = L[no << 1], R[no] = R[no << 1 | 1]; sum[no] = sum[no << 1] + sum[no << 1 | 1] -(R[no << 1] == L[no << 1 | 1]); } void Pushdown(int no) { if (is[no]) { sum[no << 1] = sum[no << 1 | 1] = 1; is[no << 1] = is[no << 1 | 1] = 1; cov[no << 1] = cov[no << 1 | 1] = cov[no]; L[no << 1] = R[no << 1] = L[no << 1 | 1] = R[no << 1 | 1] = cov[no]; cov[no] = is[no] = 0; } } void Build(int l, int r, int no) { if (l == r) L[no] = R[no] = a[rank[l]], sum[no] = 1; else { int mid = (l + r) >> 1; Build(lson); Build(rson); Pushup(no); } } void update(int l, int r, int no, int st, int en, int v) { if (st <= l&&r <= en) { L[no] = R[no] = v; cov[no] = v; sum[no] = 1; is[no] = 1; } else { int mid = (l + r) >> 1; Pushdown(no); if (en <= mid) update(lson, st, en, v); else if (st > mid) update(rson, st, en, v); else update(lson, st, en, v), update(rson, st, en, v); Pushup(no); } } int get(int l, int r, int no, int k) { if (l == r) return L[no]; else { int mid = (l + r) >> 1; Pushdown(no); if (k <= mid) return get(lson, k); else return get(rson, k); } } int query(int l, int r, int no, int st, int en) { if (st <= l&&r <= en) return sum[no]; else { int mid = (l + r) >> 1; Pushdown(no); if (en <= mid) return query(lson, st, en); else if (st > mid) return query(rson, st, en); else { int ret = query(lson, st, en) + query(rson, st, en); if (R[no << 1] == L[no << 1 | 1]) ret--; return ret; } } } void op_C(int x, int y, int v) { while (top[x] != top[y]) { if (deep[top[x]] < deep[top[y]]) swap(x, y); update(1, n, 1, p[top[x]], p[x], v); x = fa[top[x]]; } if (deep[x] < deep[y]) swap(x, y); update(1, n, 1, p[y], p[x], v); } int op_Q(int x, int y) { int ret = 0; while (top[x] != top[y]) { if (deep[top[x]] < deep[top[y]]) swap(x, y); ret += query(1, n, 1, p[top[x]], p[x]); if (get(1, n, 1, p[top[x]]) == get(1, n, 1, p[fa[top[x]]])) ret--; x = fa[top[x]]; } if (deep[x] < deep[y]) swap(x, y); ret += query(1, n, 1, p[y], p[x]); return ret; } int main() { int m, i, j, k, x, y, v; scanf("%d%d", &n, &m); for (i = 1; i <= n; i++) scanf("%d", a + i); for (i = 1; i < n; i++) { scanf("%d%d", &x, &y); to[x].push_back(y); to[y].push_back(x); } dfs1(1, 1, 0); dfs2(1, 0); Build(1, n, 1); for (i = 1; i <= m; i++) { scanf("%s", str); if (str[0] == 'C') { scanf("%d%d%d", &x, &y, &v); op_C(x, y, v); } else { scanf("%d%d", &x, &y); printf("%d ", op_Q(x, y)); } } return 0; }