• [洛谷P2486] [SDOI2011]染色


    题目链接:##

    传送门

    题目分析:##

    树链剖分经典题
    首先考虑在序列上如何维护染色与色段个数,可以很容易想到每次pushup时将左子和右子的个数合并上来,并判断一下中间是否是同一段
    在树上同理,对每个重链建线段树并如上所述维护,注意在查找答案时跳每段重链要记录端点颜色来比较,判一下两端端点颜色是否相同
    也可用LCT做,还没学,学完回来补档。
    写树剖细节很多,尽量考虑全面。

    代码:##

    //记录线段树区间左端点右端点颜色和每段重链的头尾颜色 
    
    #include<bits/stdc++.h>
    #define N (100000 + 5) 
    using namespace std;
    inline int read() {
        int cnt = 0, f = 1; char c;
        c = getchar();
        while(!isdigit(c)) {
            if (c == '-') f = -f;
            c = getchar();
        }
        while(isdigit(c)) {
            cnt = cnt * 10 + c - '0';
            c = getchar();
        }
        return cnt * f;
    }
    int n, m, a[N];
    int nxt[N<<1],	first[N], to[N<<1], tot, num[N], id[N], top[N], idx = 0, father[N], siz[N], dep[N], son[N];
    int ans1, ans2, Lc, Rc;
    int x, y, z; char opr = '0'; 
    
    struct node{
        int l, r;
        long long tag, dat, lc, rc;
        #define l(p) tree[p].l
        #define r(p) tree[p].r
        #define dat(p) tree[p].dat
        #define tag(p) tree[p].tag
        #define lc(p) tree[p].lc
        #define rc(p) tree[p].rc
    } tree[N * 4]; 
    
    void add(int x, int y) {
        nxt[++tot] = first[x];
        first[x] = tot;
        to[tot] = y;
    }
    
    void pushdown(int p);
    void pushup(int p);
    
    void debug(int p, int l, int r) {
        if(l == r) {
            //cout<<id[l]<<" "<<lc(l)<<endl;
            cout<<lc(l)<<" ";
            return;
        }
        pushdown(p);
        int mid = (l + r) >> 1;
        debug(p << 1, l, mid);
        debug(p << 1 | 1, mid + 1, r);
        pushup(p);
    }
    
    void dfs1(int cur, int fa) {
        father[cur] = fa, siz[cur] = 1, dep[cur] = dep[fa] + 1;
        for (register int i = first[cur]; i; i = nxt[i]) {
            int v = to[i];
            if (v != fa) {
                dfs1(v, cur);
                siz[cur] += siz[v];
                if (siz[son[cur]] < siz[v]) son[cur] = v;
            }
        }
    }
    
    void dfs2(int cur, int tp) {
        top[cur] = tp; num[cur] = ++idx;
        id[idx] = cur;
        if(son[cur]) dfs2(son[cur], tp);
        for (register int i = first[cur]; i; i = nxt[i]) {
            int v = to[i];
            if (!num[v]) dfs2(v, v);
        }
    }
    
    void pushup(int p) {
        lc(p) = lc(p << 1), rc(p) = rc(p << 1 | 1); 
        dat(p) = dat(p << 1) + dat(p << 1 | 1);
        if(rc(p << 1) == lc(p << 1 | 1)) --dat(p);
    }
    
    void pushdown(int p) {
        if(tag(p)) {
            tag(p << 1) = tag(p << 1 | 1) = tag(p);
            lc(p << 1) = lc(p << 1 | 1) = rc(p << 1) = rc(p << 1 | 1) = tag(p);
            dat(p << 1) = dat(p << 1 | 1) = 1;
            tag(p) = 0; 
        }
    }
    
    void build_tree(int p, int l, int r) {
        l(p) = l, r(p) = r;
        if (l == r) {
            lc(p) = rc(p) = a[id[l]];
            dat(p) = 1;
            return;
        }
        int mid = (l + r) >> 1;
        build_tree(p << 1, l, mid);
        build_tree(p << 1 | 1, mid + 1, r);
        pushup(p);
    }
    
    void modify(int p, int l, int r, int d) {
        if (l <= l(p) && r >= r(p)) {
            tag(p) = d;
            lc(p) = rc(p) = d;
            dat(p) = 1;
            return;
        }
        pushdown(p);
        int mid = (l(p) + r(p)) >> 1;
        if(l <= mid) modify(p << 1, l, r, d);
        if(r > mid) modify(p << 1 | 1, l, r, d);
        pushup(p); 
    }
    
    long long query(int p, int l, int r) {
    //	cout<<"p= "<<p<<" l(p)= "<<l(p)<<" r(p)= "<<r(p)<<endl;
        if (l(p) == l) Lc = lc(p);
        if (r(p) == r) Rc = rc(p);
    //	if(l(p)>r||r(p)<l)return 0; 
        if (l <= l(p) && r >= r(p)) {
    //		cout<<" dat(p)= "<<dat(p)<<" "<<l<<" "<<r<<endl;
            return dat(p);
        }
        pushdown(p);
        long long val = 0;
        int mid = (l(p) + r(p)) >> 1;
        if (l > mid) val += query(p << 1 | 1, l, r);
        else if (r <= mid) val += query(p << 1, l, r);
        else {
    //		cout<<val<<endl;
            if (rc(p << 1) == lc(p << 1 | 1)) val += query(p << 1, l, r) + query(p << 1 | 1, l, r) - 1;
            else val += query(p << 1, l, r) + query(p << 1 | 1, l, r); 
        }
        return val;
    }
    
    void chain_modify(int u, int v, int d) {
        while(top[u] != top[v]) {
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
            modify(1, num[top[u]], num[u], d);
            u = father[top[u]];
        }
        if (dep[u] < dep[v]) swap(u, v);
        modify(1, num[v], num[u], d);
    }
    
    long long chain_query(int u, int v) {
        long long ans = 0;
        ans1 = ans2 = 0;
        while(top[u] != top[v]) {
    //		cout<<"chain_query_start:"<<u<<" "<<v<<endl;
            if (dep[top[u]] < dep[top[v]]) swap(u, v), swap(ans1, ans2);
            ans += query(1, num[top[u]], num[u]);
    //		cout<<"fuck "<<u<<" "<<top[u]<<endl;
            if (ans1 == Rc) ans--;
            ans1 = Lc;
            u = father[top[u]];
        }
        if (dep[u] < dep[v]) swap(u, v), swap(ans1, ans2);
        ans += query(1, num[v], num[u]);
        if (Rc == ans1) ans--;
        if (Lc == ans2) ans--;
        return ans;
    }
    
    void solve() {
        n = read(); m = read();
        for (register int i = 1; i <= n; i++) a[i] = read() + 1;
        for (register int i = 1; i < n; i++) {
            x = read(); y = read();
            add(x, y); add(y, x);
        }
        dfs1(1, 0); dfs2(1, 1);
        //for(int i=1; i<=n; i++) cout<<father[i]<<" "<<top[i]<<" "<<dep[i]<<" "<<num[i]<<endl;
        build_tree(1, 1, n);
    //	cout<<"#"<<endl;
        for (register int i = 1; i <= m; i++) {
            cin >> opr;
            x = read(); y = read();
            if (opr == 'C') {
                z = read();
            //	cout<<"fffffasfasf"<<endl;
            //	debug(1, 1, n);cout<<endl;
                chain_modify(x, y, z + 1);
            //	debug(1, 1, n);
            //	cout<<endl;
            }
            if (opr == 'Q') {
                long long res = chain_query(x, y);
                printf("%lld
    ", res);
            }
        }
    }
    int main() {
        //freopen("input.in","r",stdin);
        solve();
        return 0;
    }
    
  • 相关阅读:
    Android 开发遇到的问题及解决办法
    Android Studio HelloWorld
    Android Studio与Genymontion的安装
    自定义简单版本python线程池
    唯一图库爬取图片
    网页登陆验证之图片验证码
    向后台提交数据:利用cookie加session提交更多数据,
    向后台提交数据:cookie,secure_cookie,
    利用js里的Dom和Date,自定义cookie的前端设置方法
    向后台提交数据:通过form表单提交数据需刷新网页 但通过Ajax提交数据不用刷新网页可通过原生态Ajax或jqueryAjax。Ajax代码部分
  • 原文地址:https://www.cnblogs.com/kma093/p/11055119.html
Copyright © 2020-2023  润新知