zoukankan      html  css  js  c++  java
  • [SDOI2011]染色

    题意

    Here

    思考

    树上链修改,树上链查询,考虑树链剖分

    染色操作:线段树区间修改,注意 (lazy) 数组的赋初值

    查询操作,线段树每个节点记录该段左端点颜色和右端点颜色,树上跳 (top) 的时候注意合并的处理,(如果现在端的右端点颜色等于上一段左端点颜色,就少计一种颜色),主要是细节问题,感觉还是很锻炼码力的

    代码

    #include<bits/stdc++.h>
    #define ls(pos) pos << 1
    #define rs(pos) pos << 1 | 1
    using namespace std;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x * f;
    }
    const int M = 300030;
    const int N = 300030;
    struct node{
        int nxt, to;
    }edge[M << 1];
    int head[N], num;
    void build(int from, int to){
        edge[++num].nxt = head[from];
        edge[num].to = to;
        head[from] = num;
    }
    namespace Seg{
        struct node2{
            int sum, cl, cr;
        };
        int d[N], fa[N], sz[N], son[N], top[N], seg[N], rev[N], val[N], cnt;
        void dfs(int u, int f){
            d[u] = d[f] + 1; sz[u] = 1; fa[u] = f;
            for(int i=head[u]; i; i=edge[i].nxt){
                int v = edge[i].to;
                if(v == f) continue;
                dfs(v, u);
                sz[u] += sz[v];
                if(sz[son[u]] < sz[v]) son[u] = v;
            }
        }
        void dfs2(int u, int topf){
            top[u] = topf; seg[u] = ++ cnt; rev[cnt] = u;
            if(!son[u]) return;
            dfs2(son[u], topf);
            for(int i=head[u]; i; i=edge[i].nxt){
                int v = edge[i].to;
                if(!seg[v]) dfs2(v, v);
            }
        }
        int S[N << 2], l[N << 2], r[N << 2], C[N << 2];
        void pushup(int pos){
            l[pos] = l[ls(pos)]; r[pos] = r[rs(pos)];
            if(r[ls(pos)] == l[rs(pos)]){
                S[pos] = S[ls(pos)] + S[rs(pos)] - 1;
            }
            else S[pos] = S[ls(pos)] + S[rs(pos)];
        }
        void builds(int pos, int ll, int rr){
            C[pos] = -1;
            if(ll == rr) {
                S[pos] = 1; l[pos] = r[pos] = val[rev[ll]];
                return;
            }
            int mid = (ll + rr) >> 1;
            builds(ls(pos), ll, mid);
            builds(rs(pos), mid+1, rr);
            pushup(pos);
        }
        void change(int pos, int v){
            S[pos] = 1; C[pos] = v; l[pos] = r[pos] = v;
        }
        void pushdown(int pos){
            if(C[pos] != -1){
                change(ls(pos), C[pos]);
                change(rs(pos), C[pos]);
                C[pos] = -1;
            }
        }
        void modify(int pos, int l, int r, int x, int y, int v){
            if(l > y || r < x) return;
            if(x <= l && r <= y) return change(pos, v);
            pushdown(pos);
            int mid = (l + r) >> 1;
            if(x <= mid) modify(ls(pos), l, mid, x, y, v);
            if(y > mid) modify(rs(pos), mid+1, r, x, y, v);
            pushup(pos);
        }
        node2 query(int pos, int ll, int rr, int x, int y){
            if(x <= ll && rr <= y) {
                node2 ans = (node2){S[pos], l[pos], r[pos]};
                return ans;
            }
            pushdown(pos);
            int mid = (ll + rr) >> 1;
            if(y <= mid) return query(ls(pos), ll, mid, x, y);
            else if(x > mid) return query(rs(pos), mid+1, rr, x, y);
            else{
                node2 L = query(ls(pos), ll, mid, x, y);
                node2 R = query(rs(pos), mid+1, rr, x, y);
                node2 ans;
                ans.cl = L.cl; ans.cr = R.cr;
                if(R.cl == L.cr){
                    ans.sum = L.sum + R.sum - 1;
                }
                else ans.sum = L.sum + R.sum;
                return ans;
            }
        }
        void Tmodify(int u, int v, int w){
            while(top[u] != top[v]){
                if(d[top[u]] < d[top[v]]) swap(u, v);
                modify(1, 1, cnt, seg[top[u]], seg[u], w);
                u = fa[top[u]];
            }
            if(d[u] > d[v]) swap(u, v);
            modify(1, 1, cnt, seg[u], seg[v], w);
        }
        int Tquery(int u, int v){
            int lal = -1, lar = -1, ans = 0;
            while(top[u] != top[v]){
                if(d[top[u]] < d[top[v]]) swap(u, v), swap(lal, lar);
                node2 ans1 = query(1, 1, cnt, seg[top[u]], seg[u]);
                ans += ans1.sum;
                if(lal == ans1.cr) ans --; lal = ans1.cl;
                u = fa[top[u]];
            }
            if(d[u] > d[v]) swap(u, v), swap(lal, lar);
            node2 ans1 = query(1, 1, cnt, seg[u], seg[v]);
            ans += ans1.sum;
            if(lal == ans1.cl) ans --;
            if(lar == ans1.cr) ans --;
            return ans;
        }
    }
    using namespace Seg;
    int n, m;
    int main(){
        n = read(); m = read();
        for(int i=1; i<=n; i++) val[i] = read();
        for(int i=1; i<=n-1; i++){
            int u = read(), v = read();
            build(u, v); build(v, u);
        }
        dfs(1, 0); dfs2(1, 1); builds(1, 1, cnt);
        while(m --){
            char op[10]; scanf("%s", op + 1);
            if(op[1] == 'C'){
                int a = read(), b = read(), c = read();
                Tmodify(a, b, c);
            }
            else{
                int a = read(), b = read();
                printf("%d
    ", Tquery(a, b));
            }
        }
        return 0;
    }
    
    

    总结

    比较码农的题,注意细节就 (ok) ~

  • 相关阅读:
    C/C++字符串转换函数;
    MFC CTreeCtrl 递归遍历算法
    汉字转拼音
    Windows之权限讲解
    Ubuntu 保存文件时报E212
    ON_WM_MOUSEWHEEL无响应
    sln、db、opendb、vcxproj、filters、user文件跟踪说明
    iOS 9: UIStackView入门
    Swift语言Storyboard教程:第一部分
    springboot启动项目报错:ERROR:o.s.b.d.LoggingFailureAnalysisReporter解决办法
  • 原文地址:https://www.cnblogs.com/alecli/p/9911837.html
Copyright © 2011-2022 走看看