zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    WPF之感触
    C# WinForm 给DataTable中指定位置添加列
    MyEclipse 8.6 download 官方下载地址
    将博客搬至CSDN
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
  • 原文地址:https://www.cnblogs.com/cycleke/p/6422731.html
Copyright © 2011-2022 走看看