zoukankan      html  css  js  c++  java
  • hdu 5029 Relief grain

    树的轻重链剖分。http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

    剖分完了以后一条路径等同在O(logn)条连续的线段。

    每次是区间修改,只要单点的最后结果,可以用部分和来维护。

    对于各个点的回答,用以谷物为下标的线段树维护谷物的最值。

    O(nlog^2n)

    /*********************************************************
    *            ------------------                          *
    *   author AbyssFish                                     *
    **********************************************************/
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<cmath>
    #include<numeric>
    #include<climits>
    using namespace std;
    
    
    const int maxn = 100000+5;
    
    int n, m;
    int hd[maxn], to[maxn*2], nx[maxn*2], ec;
    void add_edge(int u,int v)
    {
        to[ec] = v;
        nx[ec] = hd[u];
        hd[u] = ec++;
    }
    void init_g(int n){ memset(hd+1,0xff,4*n); ec = 0; }
    #define eachedge int i = hd[u]; ~i; i = nx[i]
    #define ifvalid int v = to[i]; if(v == fa[u]) continue;
    
    /*-----------------------------------------------*/
    int tr_sz[maxn];
    int fa[maxn];
    int dep[maxn];
    int son[maxn];
    int top[maxn];
    int id[maxn];//0 base
    int id_cnt;
    
    //1 base indexed , node0 , size[0] = 0
    void dfs(int u,int f = 0, int d = 0)
    {
        dep[u] = d;
        son[u] = 0;
        fa[u] = f;
        int &c = tr_sz[u];
        c = 1;
        for(eachedge){
            ifvalid
            dfs(v,u,d+1);
            c += tr_sz[v];
            if(tr_sz[v] > tr_sz[son[u]])
                son[u] = v;
        }
    }
    
    void sub_dv(int u,int tp)
    {
        top[u] = tp;
        id[u] = id_cnt++;
        if(son[u]) sub_dv(son[u],tp);
        for(eachedge){
            ifvalid
            if(v == son[u]) continue;
            sub_dv(v,v);
        }
    }
    
    /*-----------------------------------------------*/
    int maxz;
    #define para int o = 1, int l = 0, int r = maxz
    #define lo (o<<1)
    #define ro (o<<1|1)
    #define Tvar int md = (l+r)>>1;
    #define lsn lo,l,md
    #define rsn ro,md+1,r
    
    
    const int ST_SIZE = 1<<18;
    int fcnt[maxn];
    int fid[ST_SIZE]; //单点最值的id
    
    //food indexed
    void build(para)
    {
        fid[o] = l;
        if(l < r){
            Tvar
            build(lsn);
            build(rsn);
        }
    }
    
    inline void maintain(int o,int lc,int rc)
    {
        fid[o] = fcnt[fid[lc]] >= fcnt[fid[rc]] ? fid[lc] : fid[rc];
    }
    
    void update(int z,int d,para)
    {
        if(l == r){
            fcnt[z] += d;
        }
        else {
            Tvar
            if(z <= md) update(z,d,lsn);
            else update(z,d,rsn);
            maintain(o,lo,ro);
        }
    }
    
    
    
    /*-----------------------------------------------*/
    void init()
    {
        init_g(n);
        for(int i = 1; i < n; i++){
            int u,v; scanf("%d%d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
    
    }
    
    vector<int> p_sum[maxn];
    
    inline void add(int l,int r,int z)
    {
        p_sum[l].push_back(z);
        p_sum[r+1].push_back(-z);
    }
    
    inline void dump(int &h, int &v,int z)
    {
        add(id[h],id[v],z);
        v = fa[h];
        h = top[v];
    }
    
    int ans[maxn];
    
    void solve()
    {
        id_cnt = 0;
        dfs(1);
        sub_dv(1,1);
    
        for(int i = 0; i <= id_cnt; i++) p_sum[i].clear();
        maxz = 0;
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            maxz = max(z,maxz);
            int a = top[x], b = top[y];
            while(a != b){
                dep[a] > dep[b] ? dump(a,x,z) : dump(b,y,z);
            }
            dep[x] < dep[y] ? add(id[x],id[y],z) : add(id[y],id[x],z);
        }
        memset(fcnt+1,0,4*maxz);
        build();
        for(int i = 0; i < id_cnt; i++){
            for(int j = 0; j < (int)p_sum[i].size(); j++){
                int z = p_sum[i][j];
                z > 0? update(z,1) : update(-z,-1);
            }
            ans[i] = fid[1];
        }
        for(int i = 1; i <= n; i++){
            printf("%d
    ",ans[id[i]]);
        }
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        //cout<<log2(maxn);
        while(scanf("%d%d",&n,&m),n+m){
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    第三次作业——吉林市两日游规格说明书
    第三次作业——四则运算试题生成
    第三次作业——单元测试
    第三次作业——效能分析
    第三次作业——代码规范
    第三次作业——功能测试
    第二周程序作业
    第二周例行报告
    每周例行报告(10.8-10.14)
    每周例行报告(9.18-10.7)
  • 原文地址:https://www.cnblogs.com/jerryRey/p/5035637.html
Copyright © 2011-2022 走看看