題意:
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 ;
}