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\n", ask(u, v));
    }
    return 0;
}
posted @ 2017-02-21 10:09  cycleke  阅读(177)  评论(0编辑  收藏  举报