牛客国庆集训派对Day6 I 清明梦超能力者黄YY(树链剖分 + 线段树)

题目链接:https://www.nowcoder.com/acm/contest/206/I

题目大意:中文题面,自行自会~  —,—。

题目思路:题目要求在树上进行一条链的更新操作,很直观就能想到用树链剖分来做。本题要求的是每个结点倒数第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;
}

​

猜你喜欢

转载自blog.csdn.net/Lee_w_j__/article/details/82953789