牛客國慶集訓派對Day6 I 清明夢超能力者黃YY(樹鏈剖分 + 線段樹)
阿新 • • 發佈:2018-12-13
題目大意:中文題面,自行自會~ —,—。
題目思路:題目要求在樹上進行一條鏈的更新操作,很直觀就能想到用樹鏈剖分來做。本題要求的是每個結點倒數第k次被染色時,是被染成了什麼顏色,由於這個k是固定的,所以我們可以用線段樹來維護每個點被更新的次數,維護一條鏈上的節點被更新過的次數的最大次數。當一個區間的最大被更新次數超過k時,我們再暴力往下去找具體區間,對答案進行更新,對一個節點的答案更新完之後就將其的值設為負無窮大。由於每個點算答案的時候都只會被算到一次,所以整體的複雜度應該是 O(n*logn*logn)。(因為題目是要求倒數第k大,所以更新的時候從後往前更新就行了,問題不大)
具體實現看程式碼:
#include <bits/stdc++.h> #define fi first #define se second #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pb push_back #define MP make_pair #define lowbit(x) x&-x #define clr(a) memset(a,0,sizeof(a)) #define _INF(a) memset(a,0x3f,sizeof(a)) #define FIN freopen("in.txt","r",stdin) #define IOS ios::sync_with_stdio(false) #define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int>pii; typedef pair<ll, ll>pll; typedef pair<double, int> pdi; const int mod = 998244353; const int MX = 1e5 + 7; const int inf = 0x3f3f3f3f; int n, m, k; int MAX[MX << 2], add[MX << 2]; int ans[MX]; int fa[MX], dep[MX], id[MX], idx[MX], son[MX], top[MX], sz[MX], tot; vector<int>E[MX]; void push_up(int rt) { MAX[rt] = max(MAX[rt << 1], MAX[rt << 1 | 1]); } void push_down(int rt) { if (add[rt]) { add[rt << 1] += add[rt]; add[rt << 1 | 1] += add[rt]; MAX[rt << 1] += add[rt]; MAX[rt << 1 | 1] += add[rt]; add[rt] = 0; } } void dfs(int l, int r, int rt, int d) { if (MAX[rt] < k) return; if (l == r) { MAX[rt] = -inf; ans[idx[l]] = d; return; } push_down(rt); int m = (l + r) >> 1; dfs(lson, d); dfs(rson, d); push_up(rt); } void update(int L, int R, int d, int l, int r, int rt) { if (L <= l && r <= R) { MAX[rt]++; add[rt]++; dfs(l, r, rt, d); return; } push_down(rt); int m = (l + r) >> 1; if (L <= m) update(L, R, d, lson); if (R > m) update(L, R, d, rson); push_up(rt); } void dfs1(int u) { sz[u] = 1; son[u] = 0; for (auto v : E[u]) { if (v == fa[u]) continue; fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); sz[u] += sz[v]; if (sz[v] > sz[son[u]]) son[u] = v; } } void dfs2(int u, int tp) { id[u] = ++tot; idx[tot] = u; top[u] = tp; if (son[u]) dfs2(son[u], tp); for (auto v : E[u]) { if (v == fa[u] || v == son[u]) continue; dfs2(v, v); } } void pre_solve() { dfs1(1); dfs2(1, 1); } void Update(int u, int v, int d) { while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u, v); update(id[top[u]], id[u], d, 1, n, 1); u = fa[top[u]]; } if (dep[u] > dep[v]) swap(u, v); update(id[u], id[v], d, 1, n, 1); } struct Que { int u, v, c; } q[MX]; int main() { FIN; scanf("%d%d%d", &n, &m, &k); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); E[u].pb(v); E[v].pb(u); } pre_solve(); for (int i = 1; i <= m; i++) scanf("%d%d%d", &q[i].u, &q[i].v, &q[i].c); for (int i = m; i >= 1; i--) Update(q[i].u, q[i].v, q[i].c); for (int i = 1; i <= n; i++) printf("%d%c", ans[i], i == n ? '\n' : ' '); return 0; }