动态开点线段树操作合集

  1. 线段树合并

luogu P4556

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

namespace IO {
    template<class T>
    void _R(T &x) { cin >> x; }
    void _R(int &x) { scanf("%d", &x); }
    void _R(ll &x) { scanf("%lld", &x); }
    void _R(double &x) { scanf("%lf", &x); }
    void _R(char &x) { x = getchar(); }
    void _R(char *x) { scanf("%s", x); }
    void R() {}
    template<class T, class... U>
    void R(T &head, U &... tail) { _R(head), R(tail...); }
    template<class T>
    void _W(const T &x) { cout << x; }
    void _W(const int &x) { printf("%d", x); }
    void _W(const ll &x) { printf("%lld", x); }
    void _W(const double &x) { printf("%.16f", x); }
    void _W(const char &x) { putchar(x); }
    void _W(const char *x) { printf("%s", x); }
    template<class T, class U>
    void _W(const pair<T, U> &x) { _W(x.first), putchar(' '), _W(x.second); }
    template<class T>
    void _W(const vector<T> &x) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
    void W() {}
    template<class T, class... U>
    void W(const T &head, const U &... tail) { _W(head), putchar(sizeof...(tail) ? ' ' : '\n'), W(tail...); }
}
using namespace IO;
template <typename T> T pow(T a, long long b) {
    assert(b >= 0);
    T r = 1; while (b) { if (b & 1) r *= a; b >>= 1; a *= a; } return r;
}

const int maxn = 1e5+2;
const int maxp = 2e5*32+50;

int tot = 0, n, m;
int ls[maxp], rs[maxp], mx[maxp], c[maxp];

void pushup(int x) {
    if (mx[ls[x]] >= mx[rs[x]]) {
        mx[x] = mx[ls[x]];
        c[x] = c[ls[x]];
    } else {
        mx[x] = mx[rs[x]];
        c[x] = c[rs[x]];
    }
}

void insert(int &x, int l, int r, int y, int k) {
    if (!x) x = ++tot;
    if (l == r) {
        mx[x] += k;
        c[x] = l;
        return;
    }
    int mid = l + r >> 1;
    if (y <= mid) insert(ls[x], l, mid, y, k);
    else insert(rs[x], mid + 1, r, y, k);
    pushup(x);
}

void merge(int &x, int y, int l, int r) {
    if (!x) {
        x = y;
        return;
    }
    if (!y) return;
    if (l == r) {
        c[x] = l;
        mx[x] += mx[y];
        return;
    }
    int mid = l + r >> 1;
    merge(ls[x], ls[y], l, mid);
    merge(rs[x], rs[y], mid + 1, r);
    pushup(x);
}

vector<int> e[maxn];
int fa[maxn][22], dep[maxn];

void predo(int u, int pre, int dp) {
    fa[u][0] = pre;
    dep[u] = dp;
    for (int i = 1; i < 22; ++i) fa[u][i] = fa[fa[u][i - 1]][i - 1];
    for (auto v : e[u]) {
        if (v == pre) continue;
        predo(v, u, dp + 1);
    }
}

int lca(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    int d = dep[u] - dep[v];
    for (int i = 0; (1 << i) <= d; ++i)
        if (d >> i & 1) u = fa[u][i];
    if (u == v) return u;
    for (int i = 21; i >= 0; --i) {
        if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
    }
    return fa[u][0];
}

void dfs(int u, int pre) {
    for (auto v : e[u]) {
        if (v == pre) continue;
        dfs(v, u);
        merge(u, v, 1, maxn);
    }
}

int main() {
    R(n, m);
    for (int i = 1; i < n; ++i) {
        int u, v; R(u, v);
        e[u].push_back(v);
        e[v].push_back(u);
    }
    tot = n;
    predo(1, 0, 1);
    while (m--) {
        int x, y, z; R(x, y, z);
        insert(x, 1, maxn, z, 1);
        insert(y, 1, maxn, z, 1);
        int xy = lca(x, y);
        insert(xy, 1, maxn, z, -1);
        if (xy != 1) insert(fa[xy][0], 1, maxn, z, -1);
    }
    dfs(1, 0);
    for (int i = 1; i <= n; ++i) W(mx[i] == 0 ? 0 : c[i]);
    return 0;
}

posted @ 2021-05-07 15:45  badcw  阅读(75)  评论(0编辑  收藏  举报