bzoj-2243 染色

来源:互联网 发布:淘宝网韩版卫衣 编辑:程序博客网 时间:2024/04/30 09:57

题意:

给出一个无根树和树上每个结点的初始颜色;

然后进行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|1using 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);elseupdate(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);elsereturn 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\n", op_Q(x, y));}}return 0;}


1 0