• bzoj2243: [SDOI2011]染色


    2243: [SDOI2011]染色

    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

    Sample Output

    3

    1

    2

    HINT

    数N<=105,操作数M<=105,所有的颜色C为整数且在[0, 10^9]之间。

    题解

    太久没有写博客了,就拿这道水题骗流量先。

    此题是一个裸的树剖,直接贴代码。

    #include <cstdio>
    #include <cstring>
     
    #define N 100005
    struct edge {
        int t;
        edge *n;
        edge(int t = 0, edge *n = NULL) :
            t(t), n(n) {}
    } me[N << 1], *g[N], *ce = me;
    #define FOR(u) for (edge *it = g[u]; it; it = it->n)
    #define adde(a, b) (*ce = edge(b, g[a]), g[a] = ce++)
     
    typedef int arr[N];
    arr tp, fa, son, sz, dep, in, color, _color;
    int dfn;
    void d1(int u) {
        sz[u] = 1;
        FOR(u) if (it->t ^ fa[u]) {
            fa[it->t] = u;
            dep[it->t] = dep[u] + 1;
            d1(it->t);
            if (sz[son[u]] < sz[it->t])
                son[u] = it->t;
            sz[u] += sz[it->t];
        }
    }
    void d2(int u, int anc) {
        tp[u] = anc;
        in[u] = ++dfn;
        if (son[u]) d2(son[u], anc);
        FOR(u) if (!tp[it->t])
            d2(it->t, it->t);
    }
     
    struct node {
        int l, r, lc, rc, sum, lyc;
        node(int l = 0, int r = 0, int lc = 0, int rc = 0, int sum = 0, int lyc = -1):
            l(l), r(r), lc(lc), rc(rc), sum(sum), lyc(lyc) {}
        bool inrange(const int &x, const int &y) const {
            return x <= l && r <= y;
        }
    }C[N << 2];
    #define ls u << 1
    #define rs u << 1 | 1
     
    inline void pu(int u) {
        C[u].sum = C[ls].sum + C[rs].sum - (C[ls].rc == C[rs].lc);
        C[u].lc = C[ls].lc, C[u].rc = C[rs].rc;
    }
     
    inline void pd(int u) {
        if (~C[u].lyc) {
            int &c = C[u].lyc;
            C[ls].lc = C[ls].rc = C[ls].lyc = c;
            C[rs].lc = C[rs].rc = C[rs].lyc = c;
    		C[ls].sum = C[rs].sum = 1;
            c = -1;
        }
    }
     
    void build(int u, int l, int r) {
        if (l ^ r) {
            C[u] = node(l, r);
            int mid = (l + r) >> 1;
            build(ls, l, mid);
            build(rs, mid + 1, r);
            pu(u);
        } else
            C[u] = node(l, r, _color[l], _color[l], 1);
    }
     
    void upd(int u, const int &x, const int &y, const int &c) {
        if (C[u].inrange(x, y)) {
            C[u].lc = C[u].rc = C[u].lyc = c;
            C[u].sum = 1;
            return;
        }
        int mid = (C[u].l + C[u].r) >> 1;
        pd(u);
        if (x <= mid) upd(ls, x, y, c);
        if (y >  mid) upd(rs, x, y, c);
        pu(u);
    }
    int query(int u, const int &x, const int &y, int &lc, int &rc) {
        if (C[u].inrange(x, y) || (~C[u].lyc)) {
            lc = C[u].lc;
            rc = C[u].rc;
            return C[u].sum;
        }
        int mid = (C[u].l + C[u].r) >> 1;
        pd(u);
        if (y <= mid) return query(ls, x, y, lc, rc);
        if (x >  mid) return query(rs, x, y, lc, rc);
        int lrc, rlc, sum;
        sum = query(ls, x, y, lc, lrc) + query(rs, x, y, rlc, rc);
        return sum - (lrc == rlc);
    }
     
    void modify(int u, int v, const int &c) {
        while (tp[u] ^ tp[v]) {
            if (dep[tp[u]] < dep[tp[v]])
                u ^= v ^= u ^= v;
            upd(1, in[tp[u]], in[u], c);
            u = fa[tp[u]];
        }
        if (dep[u] < dep[v])
            u ^= v ^= u ^= v;
        upd(1, in[v], in[u], c);
    }
    #define swp(a, b) a ^= b ^= a ^= b
    int ask(int u, int v) {
        int sum = 0, ulc = -1, urc = -2, vlc = -3, vrc = -4, lc, rc;
        //query(1, in[v], in[v], vlc, vrc);
        //query(1, in[u], in[u], ulc, urc);
         
        while (tp[u] ^ tp[v]) 
            if (dep[tp[u]] < dep[tp[v]]) {
                sum = sum + query(1, in[tp[v]], in[v], lc, rc);
                if (vlc == rc) --sum;
                vlc = lc;
                v = fa[tp[v]];
            } else {
                sum += query(1, in[tp[u]], in[u], lc, rc);
                if (ulc == rc) --sum;
                ulc = lc;
                u = fa[tp[u]];
            }
        if (dep[u] < dep[v]) {
            swp(u, v);
            swp(ulc, vlc);
            swp(urc, vrc);
        }
        sum += query(1, in[v], in[u], lc, rc);
        if (rc == ulc) --sum;
        if (lc == vlc) --sum;
        return sum;
    }
     
    int main() {
        //freopen("t.in", "r", stdin);
        int n, m;
        char ops[3];
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i)
            scanf("%d", color + i);
        for (int i = 1, u, v; i < n; ++i) {
            scanf("%d%d", &u, &v);
            adde(u, v);
            adde(v, u);
        }
        d1(1);
        d2(1, 1);
        for (int i = 1; i <= n; ++i)
            _color[in[i]] = color[i];
        build(1, 1, n);
        for (int u, v, c; m; --m) {
            scanf("%s%d%d", ops, &u, &v);
            if (*ops == 'C') {
                scanf("%d", &c);
                modify(u, v, c);
            } else
                printf("%d
    ", ask(u, v));
        }
        return 0;
    }
    
  • 相关阅读:
    【tomcat8】consider increasing the maximum size of the cache
    *更新*无需root,一条命令强制全屏模式
    处理SFTP服务器上已离职用户,设置为登录禁用状态
    一个Web 持续集成工作实践
    tensorflow实战笔记(18)----textCNN
    train loss相关问题
    Spark学习(4)----ScalaTest
    scala学习(4)---Array定长数组操作
    spark学习(3)---集合
    spark学习(2)---RDD
  • 原文地址:https://www.cnblogs.com/cycleke/p/6422731.html
Copyright © 2020-2023  润新知