zoukankan      html  css  js  c++  java
  • Codeforces 191C Fools and Roads(树链拆分)

    题目链接:Codeforces 191C Fools and Roads

    题目大意:给定一个N节点的数。然后有M次操作,每次从u移动到v。问说每条边被移动过的次数。

    解题思路:树链剖分维护边,用一个数组标记就可以,不须要用线段树。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 1e5 + 5;
    
    int N, Q, ne, first[maxn], f[maxn], jump[maxn * 2];
    int id, idx[maxn], top[maxn], far[maxn], son[maxn], dep[maxn], cnt[maxn];
    
    struct Edge {
        int u, v;
        void set (int u, int v) {
            this->u = u;
            this->v = v;
        }
    }ed[maxn * 2];
    
    void dfs (int u, int pre, int d) {
        far[u] = pre;
        dep[u] = d;
        cnt[u] = 1;
        son[u] = 0;
    
        for (int i = first[u]; i + 1; i = jump[i]) {
            int v = ed[i].v;
            if (v == pre)
                continue;
            dfs(v, u, d + 1);
            cnt[u] += cnt[v];
            if (cnt[son[u]] < cnt[v])
                son[u] = v;
        }
    }
    
    void dfs(int u, int rot) {
        top[u] = rot;
        idx[u] = ++id;
        if (son[u])
            dfs(son[u], rot);
        for (int i = first[u]; i + 1; i = jump[i]) {
            int v = ed[i].v;
            if (v == far[u] || v == son[u])
                continue;
            dfs(v, v);
        }
    }
    
    inline void add_Edge(int u, int v) {
        ed[ne].set(u, v);
        jump[ne] = first[u];
        first[u] = ne++;
    }
    
    void init () {
        int u, v;
        ne = id = 0;
        memset(first, -1, sizeof(first));
        scanf("%d", &N);
        for (int i = 1; i < N; i++) {
            scanf("%d%d", &u, &v);
            add_Edge(u, v);
            add_Edge(v, u);
        }
        dfs(1, 0, 0);
        dfs(1, 1);
        for (int i = 0; i < N - 1; i++) {
            int t = i * 2;
            if (dep[ed[t].u] < dep[ed[t].v])
                swap(ed[t].u, ed[t].v);
        }
    }
    
    inline void add (int l, int r) {
        f[l]++, f[r + 1]--;
    }
    
    void solve (int u, int v) {
        int p = top[u], q = top[v];
        while (p != q) {
            if (dep[p] < dep[q]) {
                swap(p, q);
                swap(u, v);
            }
            add(idx[p], idx[u]);
    
            u = far[p];
            p = top[u];
        }
    
        if (u == v)
            return;
    
        if (dep[u] > dep[v])
            swap(u, v);
        add(idx[son[u]], idx[v]);
    }
    
    int main () {
        init();
    
        scanf("%d", &Q);
        int u, v;
        while (Q--) {
            scanf("%d%d", &u, &v);
            solve(u, v);
        }
    
        int mv = 0;
        for (int i = 1; i <= N; i++) {
            mv += f[i];
            f[i] = mv;
        }
    
        printf("%d", f[idx[ed[0].u]]);
        for (int i = 1; i < N - 1; i++)
            printf(" %d", f[idx[ed[i*2].u]]);
        printf("
    ");
        return 0;
    }

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    docker安装&镜像加速
    CentOS安装python3
    Elasticsearch相关下载地址
    fiddler抓包手机和小程序
    locust简单入门演示(一)——任务等待机制
    win10下载openssl
    XGBoost参数调优完全指南(转)
    HIVE学习
    windows定期清理指定目录文件(保留指定天数日志)
    RedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4830012.html
Copyright © 2011-2022 走看看