1. 程式人生 > >牛客國慶集訓派對Day6 I 清明夢超能力者黃YY(樹鏈剖分 + 線段樹)

牛客國慶集訓派對Day6 I 清明夢超能力者黃YY(樹鏈剖分 + 線段樹)

題目大意:中文題面,自行自會~  —,—。

題目思路:題目要求在樹上進行一條鏈的更新操作,很直觀就能想到用樹鏈剖分來做。本題要求的是每個結點倒數第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;
}