zoukankan      html  css  js  c++  java
  • [BZOJ2243][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<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

    Source

     

     
    裸的树链剖分,计算答案的时候注意判断一下两条链相邻的两个颜色是否一样,如果一样就减一。
    线段树的pushup同理。
     

     
    #include <iostream>
    #include <cstdio>
    using namespace std;
    #define reg register
    inline int read() {
        int res = 0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return res;
    }
    #define N 100005
    int n, m;
    struct edge {
        int nxt, to;
    }ed[N*2];
    int head[N], cnt;
    inline void add(int x, int y) {
        ed[++cnt] = (edge){head[x], y};
        head[x] = cnt;
    }
    
    int a[N];
    int siz[N], fa[N], dep[N], top[N];
    int id[N], rnk[N], son[N];
    
    void dfs(int x, int fe)
    {
        siz[x] = 1, fa[x] = fe, dep[x] = dep[fe] + 1;
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fe) continue;
            dfs(to, x);
            siz[x] += siz[to];
            if (siz[to] > siz[son[x]]) son[x] = to;
        }
    }
    
    void efs(int x, int tep)
    {
        top[x] = tep, id[x] = ++cnt, rnk[cnt] = x;
        if (son[x]) efs(son[x], tep);
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fa[x] or to == son[x]) continue;
            efs(to, to);
        }
    }
    
    struct SegMent {
        int lc, rc, dat, lazy;
    }tr[N<<2];
    #define ls(o) o << 1
    #define rs(o) o << 1 | 1
    #define lc(o) tr[o].lc
    #define rc(o) tr[o].rc
    #define dat(o) tr[o].dat
    #define lazy(o) tr[o].lazy
    
    inline void pushup(int o)
    {
        if (rc(ls(o)) == lc(rs(o))) dat(o) = dat(ls(o)) + dat(rs(o)) - 1;
        else dat(o) = dat(ls(o)) + dat(rs(o));
        lc(o) = lc(ls(o)), rc(o) = rc(rs(o));
    }
    
    void Build(int l, int r, int o)
    {
        if (l == r) {
            lc(o) = a[rnk[l]];
            rc(o) = a[rnk[l]];
            dat(o) = 1;
            lazy(o) = 0;
            return ;
        }
        int mid = l + r >> 1;
        Build(l, mid, ls(o));
        Build(mid + 1, r, rs(o));
        pushup(o);
    }
    
    inline void pushdown(int o)
    {
        if (!lazy(o)) return ;
        int c = lazy(o);
        
        lc(ls(o)) = c, rc(ls(o)) = c;
        dat(ls(o)) = 1, lazy(ls(o)) = c;
        
        lc(rs(o)) = c, rc(rs(o)) = c;
        dat(rs(o)) = 1, lazy(rs(o)) = c;
            
        lazy(o) = 0;
    }
    
    void change(int l, int r, int o, int ql, int qr, int c)
    {
        if (l >= ql and r <= qr) 
        {
            lc(o) = c, rc(o) = c;
            dat(o) = 1;
            lazy(o) = c;
            return ;
        }
        pushdown(o);
        int mid = l + r >> 1;
        if (ql <= mid) change(l, mid, ls(o), ql, qr, c);
        if (qr > mid) change(mid + 1, r, rs(o), ql, qr, c);
        pushup(o);
    }
    
    int query(int l, int r, int o, int ql, int qr)
    {
        if (l >= ql and r <= qr) return dat(o);
        pushdown(o);
        int mid = l + r >> 1;
        int res = 0;
        if (ql <= mid) res += query(l, mid, ls(o), ql, qr);
        if (qr > mid) res += query(mid + 1, r, rs(o), ql, qr);
        if (ql <= mid and qr > mid and rc(ls(o)) == lc(rs(o))) res--;
        return res;
    }
    
    int Find(int l, int r, int o, int p) 
    {
        if (l == r) return lc(o);
        pushdown(o);
        int mid = l + r >> 1;
        if (p <= mid) return Find(l, mid, ls(o), p);
        else return Find(mid + 1, r, rs(o), p);
    }
    
    inline void changes(int x, int y, int c)
    {
        while(top[x] != top[y]) 
        {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
            change(1, n, 1, id[top[x]], id[x], c);
            x = fa[top[x]];
        }
        if (id[x] > id[y]) swap(x, y);
        change(1, n, 1, id[x], id[y], c);
    }
    
    inline int querys(int x, int y)
    {
        int res = 0;
        int lst1 = 0, lst2 = 0;
        while(top[x] != top[y]) 
        {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
            res += query(1, n, 1, id[top[x]], id[x]);
            lst1 = Find(1, n, 1, id[top[x]]), lst2 = Find(1, n, 1, id[fa[top[x]]]);
            if (lst1 == lst2) res--;
            x = fa[top[x]];
        }
        if (id[x] > id[y]) swap(x, y);
        res += query(1, n, 1, id[x], id[y]);
        return res;
    }
    
    int main()
    {
        n = read(), m = read();
        for (reg int i = 1 ; i <= n ; i ++) a[i] = read();
        for (reg int i = 1 ; i < n ; i ++)
        {
            int x = read(), y = read();
            add(x, y), add(y, x);
        }
        cnt = 0;
        dep[1] = 1;
        dfs(1, 0), efs(1, 1);
        Build(1, n, 1);
        while(m--)
        {
            char ch;
            cin >> ch;
            if (ch == 'C') {
                int x = read(), y = read(), z = read();
                changes(x, y, z);
            } else {
                int x = read(), y = read();
                printf("%d
    ", querys(x, y));
            }
        }
        return 0;
    }
  • 相关阅读:
    方法永远比借口多
    node.js学习在页面上传图片并显示例子
    (转)负载大逃亡:四十二路怪兽联军及七条逃生法则
    node.js学习一例子
    node.js学习总结
    UML项目应用理解快速了解整个系统架构和详细设计文档
    position与relative的区别
    人生有四件事不可以等待
    这是我的第一篇文章
    麦咖啡8.5i 使用设置图解
  • 原文地址:https://www.cnblogs.com/BriMon/p/9592906.html
Copyright © 2011-2022 走看看