BZOJ 2243: [SDOI2011]染色 树链剖分 区间合并

来源:互联网 发布:淘宝上哪家卖玉的店铺 编辑:程序博客网 时间:2024/05/19 06:19
题意:

1、将节点a到节点b路径上所有点都染成颜色c

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

思路:很明显需要一总数据结构来维护颜色

        只是统计答案时 我门需要知道这段区间与下一段区间的联系  所以需要区间合并

       对于不在重链上的点 我们看他与他的父亲颜色是否一样 加入一样贡献减1

       对于lca位置不需要检查 直接统计答案

code:

#include<bits/stdc++.h>using namespace std;const int maxn = 1000010;int head[maxn], ecnt;struct EDGE{    int to, next;} edge[maxn << 1];void init(){    ecnt = 0;    memset(head, -1, sizeof head);}void eadd(int u, int v){    edge[ecnt] = {v, head[u]};    head[u] = ecnt++;}int dad[maxn], sz[maxn], son[maxn], deep[maxn];void dfs_1(int u, int fa){    deep[u] = deep[fa] + 1, sz[u] = 1, dad[u] = fa;    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].to;        if(v == fa) continue;        dfs_1(v, u);        sz[u] += sz[v];        if(!son[u] || sz[v] > sz[son[u]]) son[u] = v;    }}int tid[maxn], top[maxn], tidclk ;void dfs_2(int u, int topu){    top[u] = topu, tid[u] = ++tidclk;    if(!son[u]) return;    dfs_2(son[u], topu);    for(int i = head[u]; i!=-1; i = edge[i].next)    {        int v = edge[i].to;        if(v == dad[u] || v == son[u]) continue;        dfs_2(v, v);    }}struct node{    int l, r;    int ans, lc, rc, c;} tree[maxn << 2];void pushup(int root){    tree[root].lc = tree[root << 1].lc, tree[root].rc = tree[root << 1 | 1].rc;    if(tree[root << 1].rc == tree[root << 1 | 1].lc)        tree[root].ans = tree[root << 1].ans + tree[root << 1 | 1].ans - 1;    else        tree[root].ans = tree[root << 1].ans + tree[root << 1 | 1].ans;}void pushdown(int root){    if(tree[root].c)    {        tree[root << 1 | 1].ans = 1;        tree[root << 1 | 1].lc = tree[root << 1 | 1].rc = tree[root << 1 | 1].c = tree[root].c;        tree[root << 1].ans = 1;        tree[root << 1].lc = tree[root << 1].rc = tree[root << 1].c = tree[root].c;        tree[root].c = 0;    }}void build(int root, int l, int r){    tree[root].l = l, tree[root].r = r;    if(l == r)    {        tree[root].ans = tree[root].lc = tree[root].rc = tree[root].c = 0;    }    else    {        int mid = (l + r) >> 1;        build(root << 1, l, mid);        build(root << 1 | 1, mid + 1, r);        pushup(root);    }}void change(int root, int l, int r, int c){    if(l <= tree[root].l && tree[root].r <= r)    {        tree[root].ans = 1;        tree[root].lc = tree[root].rc  = tree[root].c = c;    }    else    {        pushdown(root);        int mid = (tree[root].l + tree[root].r) >> 1;        if(l <= mid) change(root << 1, l, r, c);        if(mid < r) change(root << 1 | 1, l, r, c);        pushup(root);    }}int querry(int root, int l, int r){    if(l <= tree[root].l && tree[root].r <= r)    {        return tree[root].ans;    }    else    {        pushdown(root);        int mid = (tree[root].l + tree[root].r) >> 1;        int ans = 0;        if(l <= mid) ans += querry(root << 1, l, r);        if(r >  mid) ans += querry(root << 1 | 1, l, r);        if(l <= mid && r >  mid && tree[root << 1].rc == tree[root << 1 | 1].lc) ans -= 1;        return ans;    }}int querryc(int root, int pos){    if(tree[root].l == tree[root].r)    {        return tree[root].lc;    }    pushdown(root);    int mid = (tree[root].l + tree[root].r) >> 1;    if(pos <= mid) return querryc(root << 1, pos);    if(pos > mid ) return querryc(root << 1 | 1, pos);}int querry(int u, int v){    int ans = 0;    while(top[u] != top[v])    {        if(deep[top[u]] < deep[top[v]]) swap(u, v);        ans += querry(1, tid[top[u]], tid[u]);        if(querryc(1, tid[top[u]]) == querryc(1, tid[dad[top[u]]])) ans--;        u = dad[top[u]];    }    if(deep[u] > deep[v]) swap(u, v);    ans += querry(1, tid[u], tid[v]);    return ans;}void update(int u, int v, int c){    while(top[u] != top[v])    {        if(deep[top[u]] < deep[top[v]]) swap(u, v);        change(1, tid[top[u]], tid[u], c);        u = dad[top[u]];    }    if(deep[u] > deep[v]) swap(u, v);    change(1, tid[u], tid[v], c);}int a[maxn];int main(){    init();    int n, m;scanf("%d%d", &n, &m);    for(int i = 1; i <= n; i++)        scanf("%d", &a[i]);    for(int i = 1; i <= n - 1; i++)    {        int u, v;        scanf("%d%d", &u, &v);        eadd(u, v), eadd(v, u);    }    dfs_1(1, 0), dfs_2(1, 1);    build(1, 1, n);    for(int i = 1; i <= n; i++) change(1, tid[i], tid[i], a[i]);    for(int i = 1; i <= m; i++)    {        char op[5];        scanf("%s", op + 1);        if(op[1] == 'C')        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            update(a, b, c);        }        else        {            int a, b;            scanf("%d%d", &a, &b);            printf("%d\n", querry(a, b));        }    }    return 0;}