• P2486 [SDOI2011]染色


    P2486 [SDOI2011]染色

    链接:https://www.luogu.org/problemnew/show/P2486

    题目描述

    输入输出格式

    输入格式:

    输出格式:

    对于每个询问操作,输出一行答案。

    输入输出样例

    输入样例#1: 复制
    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
    
    输出样例#1: 复制
    3
    1
    2
    

    说明

    题解:树连剖分+细节,用二进制记录某段染色情况,并记录最边上的颜色,不能维护一段中连续颜色数(显然);

    线段树查询的时候要注意合并两端细节,树剖时也要记录上次最边上的颜色,注意是父亲的;

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 100005;
    int n,m;
    struct edge{
        int v,nxt;
    }G[maxn << 1];
    int h[maxn], tot, dfn[maxn], siz[maxn], fa[maxn], top[maxn], son[maxn], in[maxn], dep[maxn], idx;
    int a[maxn],LLC,RRC;
    void add(int u, int v){
        G[++tot].nxt = h[u];
        G[tot].v = v;
        h[u] = tot;
    
    }
    void dfs1(int u, int f){
        fa[u] = f;
        siz[u] = 1;
        dep[u] = dep[f] + 1;
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(v == f)continue;
            dfs1(v, u);
            siz[u] += siz[v];
            if(siz[son[u]] < siz[v]) son[u] = v;
        }
    }
    void dfs2(int u, int f){
        in[u] = ++idx;
        top[u] = f;
        dfn[idx] = a[u];
        if(son[u])dfs2(son[u], f);
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(v == fa[u] || v == son[u])continue;
            dfs2(v, v);
        }
    }
    
    
    struct Node{
        int sum, lc, rc, delta;
        Node *ls, *rs;
        void down(int l, int r){
            if(delta == -1)return;
            ls -> delta = rs -> delta = delta;
            ls -> lc = rs -> lc = ls -> rc = rs -> rc = delta;
            ls -> sum = rs -> sum = 1;
            delta = -1;
        }
        void up(){
            sum = ls -> sum + rs -> sum;
            lc = ls -> lc; rc = rs -> rc;
            if(ls -> rc == rs -> lc)sum--;
        }
    
    }pool[maxn << 2], *root, *tail = pool;
    
    #define Ls l, m, nd->ls
    #define Rs m+1, r, nd->rs
    Node * build(int l = 1, int r = n){
        Node * nd = ++ tail;
        if(l == r){
            nd -> lc = nd -> rc = dfn[l];
            nd -> delta = -1;nd->sum = 1;
        }
        else {
            int m = (l + r) >> 1;
            nd -> ls = build(l, m);
            nd -> rs = build(m+1, r);
            nd -> up();
            nd -> delta = -1;
        }
        //printf("%d %d     %d %d kkk
    ",l,r,nd->lc,nd->rc);
        return nd;
    }
    void modify(int delta, int L, int R, int l = 1, int r = n, Node * nd = root){
        if(L <= l && R >= r){
            nd -> delta = nd -> lc = nd -> rc = delta; nd -> sum = 1;
        }
        else {
            nd -> down(l, r);
            int m = (l + r) >> 1;
            if(L <= m)modify(delta, L, R, Ls);
            if(R > m)modify(delta, L, R, Rs);
            nd -> up();
        }
    }
    int query(int L, int R, int l = 1, int r = n, Node * nd = root){
        //printf("%d %d     %d %d
    ",l,r,nd->lc,nd->rc);
        if(l == L)LLC = nd->lc;
        if(r == R)RRC = nd->rc;
        if(L <= l && R >= r)return nd -> sum;
        nd -> down(l, r);
        int ans = 0;
        int m = (l + r) >> 1;
        if(L <= m)ans += query(L, R, Ls);
        if(R > m)ans += query(L, R, Rs);
        if(L <= m && R > m && nd -> ls -> rc == nd -> rs -> lc)ans--;
        return ans;
    }
    int lca_query(int u, int v){
        int ans = 0, ans1 = -1, ans2 = -1;
        while(top[u] != top[v]){
            if(dep[top[u]] < dep[top[v]])
                swap(u, v), swap(ans1, ans2);
            ans += query(in[top[u]], in[u]);
            u = fa[top[u]];
            if(ans1 == RRC)ans--;
            ans1 = LLC;
        }
        if(dep[u] < dep[v])
            swap(u, v), swap(ans1, ans2);
        ans += query(in[v], in[u]);
        if(ans1 == RRC)ans--;
        if(ans2 == LLC)ans--;
        return ans;
    
    
    }
    void lca_modify(int u, int v, int del){
        while(top[u] != top[v]){
            if(dep[top[u]] < dep[top[v]])
                swap(u, v);
            modify(del, in[top[u]], in[u]);
            u = fa[top[u]];
        }
        if(dep[u] < dep[v])swap(u, v);
        modify(del, in[v], in[u]);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++)scanf("%d",&a[i]);
        for(int i = 1; i < n; i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u, v);add(v,u);
        }
        dfs1(1, 0);
        dfs2(1, 0);
        root = build();
        while(m--){
            char Q;
            int l, r, del;
            cin>>Q;
            if(Q == 'C'){
                scanf("%d%d%d",&l,&r,&del);
                lca_modify(l, r, del);
            }
            else {
                scanf("%d%d",&l,&r);
                printf("%d
    ",lca_query(l, r));
            }
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    BZOJ4036 HAOI2015按位或(概率期望+容斥原理)
    洛谷p2661信息传递题解
    洛谷P1434滑雪题解及记忆化搜索的基本步骤
    二分图最大匹配
    线段树

    图论基本算法
    并查集
    RMQ--ST表
    矩阵快速幂和矩阵乘法
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8992606.html
Copyright © 2020-2023  润新知