zoukankan      html  css  js  c++  java
  • Gym102059A Coloring Roads

    Gym102059A Coloring Roads


    题意:(n)点的树,一开始每条边都没有颜色,有(Q)个操作,每次将从(u)(1)路径上的所有边全部染色为颜色(c),之后询问整棵树上,出现了(m)次的颜色有多少种。数据范围均是(200000)

    做法:询问的东西十分奇怪没有办法下手,于是注意到每次的修改都是染色,而且染色的路径也很特殊。于是我们猜测在这种操作方式下,一条路径上连续相同的颜色段数有一个比较优秀的期望值。先考虑如何在一个序列上,进行赋值操作,我们想到了(ODT),在修改的同时维护每种颜色出现的次数和每种次数对应的颜色的种类数。对于每次询问的路径,通过树剖把问题转化到为序列上处理。。。

    #include <bits/stdc++.h>
    #define rep(i,a,b) for(int i = a; i <= b; ++i)
    #define pb push_back
    typedef long long ll;
    const int N = 1 << 18 | 5;
    template<class T> inline void read(T &x) {
        x = 0; char c = getchar(); T f = 1;
        while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
        while(isdigit(c)) {x = x * 10 + c - '0'; c = getchar();}
        x *= f;
    }
    using namespace std;
    int n, C, Q;
    vector<int> G[N];
    int id[N], dfn, top[N], fa[N], sz[N], son[N];
    void dfs1(int u, int pre) {
        sz[u] = 1; fa[u] = pre;
        int weight = 0;
        for(int v: G[u]) if(v != pre) {
            dfs1(v, u);
            sz[u] += sz[v];
            if(weight < sz[v]) weight = sz[v], son[u] = v;
        }
    }
    void dfs2(int u, int tp) {
        top[u] = tp; id[u] = ++dfn;
        if(son[u]) dfs2(son[u],tp);
        for(int v: G[u]) if(v != fa[u] && v != son[u]) {
            dfs2(v,v);
        }
    }
    int ans[N], col[N];
    struct Seg{
        int l, r, c;
        bool operator < (const Seg &a) const {
            return r < a.r;
        }
    };
    set< Seg > S;
    void split(int p) {
        auto s = S.lower_bound({p,p});
        if(s == S.end() || (s->l) > p || p == s->r) return;
        int L = s->l, R = s->r, C = s->c;
        S.erase(s); S.insert({L,p,C}); S.insert({p+1,R,C});
    }
    void update(int L, int R, int C) {
        split(L-1); split(R);
        while(1) {
            auto s = S.lower_bound({L,L});
            if(s == S.end() || (s->l) > R) break;
            if(s->c) {
                -- ans[col[s->c]];
                col[s->c] -= s->r - s->l + 1;
                ++ ans[col[s->c]];
            }
            S.erase(s);
        }
        -- ans[col[C]];
        col[C] += R-L+1;
        ++ ans[col[C]];
        S.insert({L,R,C});
    }
    void solve(int u, int c) {
        while(u > 1) {
            int L = max(id[top[u]],2), R = id[u];
            if(L <= R) update(L,R,c);
            u = fa[top[u]];
        }
    }
    int main() {
        read(n), read(C), read(Q);
        rep(i,2,n) { int u, v;
            read(u), read(v);
            G[u].pb(v), G[v].pb(u);
        }
        dfs1(1,0); dfs2(1,1);
        ans[0] = C;
        S.insert({2,n,0});
        while(Q--) { int u, c, m;
            read(u), read(c), read(m);
            solve(u,c);
            printf("%d
    ",ans[m]);
        }
    }
    
  • 相关阅读:
    关于乔布斯,互联网上全部的视频资源有哪些
    Spring MVC 文件下载最佳实践
    HMC 的升级方法
    linux软件包合集
    9117-MMA几种具有分离背板(split backplane)功能选件的区别
    Utility Capacity on Demand(服务器按需扩容技术)
    ent en et的区别
    IBM-UK ftp资料站
    ntpd和chrony
    bosboot -a的作用
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/10487085.html
Copyright © 2011-2022 走看看