zoukankan      html  css  js  c++  java
  • 树链剖分处理+线段树解决问题 HDU 5029

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5029

    题意:n个点的树,m次操作。每次操作输入L,R,V,表示在[L,R]这个区间加上V这个数字。比如[1,2]加上1,[1,3]加上1,那么1这个点就是{1,1},2也是{1,1},3是{1}。全部操作操作完之后,输出每个点中,最多的那个数字有几个。如果有相同的数字,就输出最小的那个数。比如{1,1,2,2},就输出1。

    思路:树链剖分拍成链,然后通过找LCA,来离线预处理,然后最后通过离线暴力一遍线段树,来完成询问操作(md,add这个函数错了4个小时TAT)

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 1e5 + 5;
    int belong[maxn], pos[maxn], son[maxn], id[maxn];
    int par[maxn], sz[maxn], deep[maxn], ans[maxn];
    int n, m, dfstime;
    vector<int> G[maxn];
    vector<pair<int, int> > color[maxn];
    int tree[maxn << 2];
    
    void init(){
        for (int i = 1; i <= n; i++) G[i].clear();
        for (int i = 1; i <= 100000; i++) color[i].clear();
        memset(belong, 0, sizeof(belong));
        memset(son, 0, sizeof(son));
        memset(par, 0, sizeof(par));
        memset(deep, 0, sizeof(deep));
        memset(sz, 0, sizeof(sz));
        for (int i = 1; i < n; i++){
            int u, v; scanf("%d%d", &u, &v);
            G[u].pb(v), G[v].pb(u);
        }
    }
    
    void dfs_size(int u, int fa, int road){
        deep[u] = road, par[u] = fa;
        sz[u] = 1;
        for (int i = 0; i < G[u].size(); i++){
            int v = G[u][i];
            if (v == fa) continue;
            dfs_size(v, u, road + 1);
            sz[u] += sz[v];
            if (sz[v] > sz[son[u]]) son[u] = v;
        }
    }
    
    void dfs_tree(int u, int fa, int chain){
        pos[u] = ++dfstime; belong[u] = chain; id[dfstime] = u;
        if (son[u] == 0) return ;
        dfs_tree(son[u], u, chain);
        for (int i = 0; i < G[u].size(); i++){
            int v = G[u][i];
            if (v == fa || v == son[u]) continue;
            dfs_tree(v, u, v);
        }
    }
    
    void add(int x, int y, int c){///加入边
        while (belong[x] != belong[y]){
            if (deep[belong[x]] < deep[belong[y]]) swap(x, y);
            color[pos[belong[x]]].push_back(mk(c, 1));
            color[pos[x] + 1].push_back(mk(c, -1));
            x = par[belong[x]];
        }
        if (deep[x] < deep[y]) swap(x, y);
        color[pos[y]].push_back(mk(c, 1)), color[pos[x] + 1].push_back(mk(c, -1));
    }
    
    void update(int p, int l, int r, int o, int val){
        if (p == l && p == r){
            tree[o] += val; return ;
        }
        int mid = (l + r) / 2, lb = o << 1, rb = o << 1 | 1;
        if (p <= mid) update(p, l, mid, lb, val);
        if (p > mid) update(p, mid + 1, r, rb, val);
        tree[o] = max(tree[lb], tree[rb]);
    }
    
    int query(int l, int r, int o){
        if (l == r) {
            if (tree[o] == 0) return 0;
            return l;
        }
        int mid = (l + r) / 2, lb = o << 1 , rb = o << 1 | 1;
        if (tree[lb] >= tree[rb]) return query(l, mid, lb);
        else return query(mid + 1, r, rb);
    }
    
    int main(){
        while (scanf("%d%d", &n, &m) == 2){
            if (n == 0 && m == 0) break;
            init(); dfstime = 0;
            dfs_size(1, 0, 1);
            dfs_tree(1, 0, 1);
            for (int i = 1; i <= m; i++){
                int x, y, z; scanf("%d%d%d", &x, &y, &z);
                add(x, y, z);
            }
            memset(tree, 0, sizeof(tree));
            for (int i = 1; i <= n; i++){
                for (int j = 0; j < color[i].size(); j++){
                    int c = color[i][j].first, val = color[i][j].second;
                    update(c, 1, 100000, 1, val);
                }
                ans[id[i]] = query(1, 100000, 1);
            }
            for (int i = 1; i <= n; i++){
                printf("%d
    ", ans[i]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    OpenCv 109---Blob分析
    OpenCv 013---图像的翻转
    OpenCv 012---视频文件读写
    MenuExample
    OpenCv 011---像素归一化
    OpenCv 010---图像像素值统计
    OpenCv 009---色彩空间与色彩空间转换
    OpenCv 008---通道分离与合并
    OpenCv 007---像素操作的逻辑操作
    OpenCv 006---LUT的作用与用法
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6498176.html
Copyright © 2011-2022 走看看