天天看點

HDU 5029 Relief grain (樹鍊剖分 + 線段樹)

題意:

N<=105的一棵樹,Q<=105

每個操作都在兩點的路徑上配置設定糧食類型(Z<=105種)+1

最後輸出所有村莊有的最多的糧食的種類

分析:

首先樹鍊剖分是很顯然的,關鍵是怎麼維護每個點的最大糧食種類,Z<=105太大了

考慮把操作離線,維護糧食類型,對區間[l,r]加z,可以在l加一個z,在r+1減掉一個z

這樣我們在更新過程中把更新操作離線,最後統一更新答案就好啦

然後模版一套就是水題了

代碼:

//
//  Created by TaoSama on 2015-10-23
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N =  + , INF = , MOD =  + ;

int n, q;
vector<int> add[N], sub[N];

struct Node {
    int l, r;
    int maxv, type;
};

struct SegTree {
    Node dat[N << ];

    void push_up(int rt) {
        int ls = rt << , rs = ls | ;
        if(dat[rs].maxv > dat[ls].maxv) {
            dat[rt].maxv = dat[rs].maxv;
            dat[rt].type = dat[rs].type;
        } else {
            dat[rt].maxv = dat[ls].maxv;
            dat[rt].type = dat[ls].type;
        }
    }

    void build(int l, int r, int rt) {
        dat[rt].l = l, dat[rt].r = r, dat[rt].maxv = ;
        if(l == r) {
            dat[rt].type = l;
            return;
        }
        int m = l + r >> ;
        build(l, m, rt << );
        build(m + , r, rt <<  | );
        push_up(rt);
    }

    void update(int o, int v, int rt) {
        if(dat[rt].l == dat[rt].r) {
            dat[rt].maxv += v;
            return;
        }
        int m = dat[rt].l + dat[rt].r >> ;
        if(o <= m) update(o, v, rt << );
        else update(o, v, rt <<  | );
        push_up(rt);
    }
} T;

struct Edge {
    int to, nxt;
};

struct HLD {
    int head[N], cnt, tid;
    int sz[N], son[N], fa[N], dep[N], top[N], dfn[N], wh[N];
    Edge edge[N << ];

    void init() {
        cnt = tid = ;
        memset(head, -, sizeof head);
        memset(son, , sizeof son);
    }

    void add_edge(int u, int v) {
        edge[cnt] = (Edge) {v, head[u]};
        head[u] = cnt++;
        edge[cnt] = (Edge) {u, head[v]};
        head[v] = cnt++;
    }
    //find heavy edge
    void dfs1(int u, int f, int d) {
        sz[u] = , fa[u] = f, dep[u] = d;
        for(int i = head[u]; ~i; i = edge[i].nxt) {
            int v = edge[i].to;
            if(v == f) continue;
            dfs1(v, u, d + );
            if(!son[u] || sz[v] > sz[son[u]]) son[u] = v;
            sz[u] += sz[v];
        }
    }
    //connect heavy edge
    void dfs2(int u, int tp) {
        dfn[u] = ++tid;
        wh[tid] = u;
        top[u] = tp;
        if(son[u]) dfs2(son[u], tp);
        for(int i = head[u]; ~i; i = edge[i].nxt) {
            int v = edge[i].to;
            if(v == fa[u] || v == son[u]) continue;
            dfs2(v, v);
        }
    }

    void update(int u, int v, int c) {
        int fu = top[u], fv = top[v];
        while(fu != fv) {
            if(dep[fu] < dep[fv]) {
                swap(u, v);
                swap(fu, fv);
            }
            add[dfn[fu]].push_back(c);
            sub[dfn[u] + ].push_back(c);
            u = fa[fu];
            fu = top[u];
        }
        if(dep[u] > dep[v]) swap(u, v);
        add[dfn[u]].push_back(c);
        sub[dfn[v] + ].push_back(c);
    }

    void build() {
        dfs1(, -, );
        dfs2(, );
    }
};

HLD hld;

int ans[N];

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    while(scanf("%d%d", &n, &q) ==  && (n || q)) {
        hld.init();
        for(int i = ; i <= n; ++i) add[i].clear(), sub[i].clear();
        for(int i = ; i < n; ++i) {
            int u, v; scanf("%d%d", &u, &v);
            hld.add_edge(u, v);
        }
        hld.build();
        while(q--) {
            int x, y, z; scanf("%d%d%d", &x, &y, &z);
            hld.update(x, y, z);
        }

        T.build(, , );
        for(int i = ; i <= n; ++i) {
            for(auto c : add[i]) T.update(c, , );
            for(auto c : sub[i]) T.update(c, -, );
            int u = hld.wh[i];
            if(T.dat[].maxv == ) ans[u] = ;
            else ans[u] = T.dat[].type;
        }
        for(int i = ; i <= n; ++i) printf("%d\n", ans[i]);
    }
    return ;
}