「BZOJ 3720」Gty的妹子树

维护初始有 \(n\) 个节点的有根树(根节点为 \(1\) ),树上节点编号为 \(1 \sim n\) ,每个点有一个权值 \(w_i\)
支持以下操作:

  • 0 u x 询问以 \(u\) 为根的子树中,严格大于 \(x\) 的值的个数。
  • 1 u x\(u\) 节点的权值改成 \(x\)
  • 2 u x 添加一个编号为“当前树中节点数 + 1 ”的节点,其父节点为 \(u\) ,其权值为 \(x\)
    本题强制在线。
    \(1\le n,m\le 30,000\)

Luogu

BZOJ

分析

显然可以用分块做,也可以用主席树来做,但是第三个操作不好处理。

简单的树上分块会被菊花图卡,所以我被卡了。。。。。。

代码

卡常 + 吸氧 1.73s

不吸氧会 T 三个点。

#include <bits/stdc++.h>

#define N 60001
#define rg register

using namespace std;

inline int gi() {
    rg int x = 0, f = 1; rg char c = getchar();
    for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return x * f;
}

int n, m, blo, ans, tot;
int fa[N], bel[N], val[N];
int to[N << 1], nxt[N << 1], hd[N], cnt;

vector <int> g[N], bl[N];
vector <int> :: iterator it;

void insert(int u, int v) { to[++cnt] = v, nxt[cnt] = hd[u]; hd[u] = cnt; }

inline void dfs(int u, int f) {
    fa[u] = f;
    if (bl[bel[f]].size() == blo) bel[u] = ++tot, g[bel[f]].push_back(tot);
    else bel[u] = bel[f];
    bl[bel[u]].push_back(val[u]);
    for (rg int i = hd[u]; i; i = nxt[i]) {
        rg int v = to[i];
        if (v == f) continue;
        dfs(v, u);
    }
}

inline void change(int u, int x) {
    it = lower_bound(bl[bel[u]].begin(), bl[bel[u]].end(), val[u]);
    *it = x, val[u] = x;
    sort(bl[bel[u]].begin(), bl[bel[u]].end());
}

inline void add(int u, int x) {
    fa[++n] = u, val[n] = x;
    insert(u, n);
    if (bl[bel[u]].size() == blo) {
        bel[n] = ++tot;
        g[bel[u]].push_back(tot);
        bl[tot].push_back(x);
    }
    else {
        bel[n] = bel[u];
        bl[bel[u]].push_back(x);
        sort(bl[bel[u]].begin(), bl[bel[u]].end());
    }
}

inline int get(int u, int k) {
    rg int ret = bl[u].end() - upper_bound(bl[u].begin(), bl[u].end(), k);
    for (rg int i = 0; i < g[u].size(); ++i) {
        rg int v = g[u][i];
        ret += get(v, k);
    }
    return ret;
}

inline int query(int u, int k) {
    rg int ret = 0;
    if (val[u] > k) ret++;
    for (rg int i = hd[u]; i; i = nxt[i]) {
        rg int v = to[i];
        if (v == fa[u]) continue;
        if (bel[v] == bel[u]) ret += query(v, k);
        else ret += get(bel[v], k);
    }
    return ret;
}

int main() {
    rg int u, v, op;
    n = gi(), blo = sqrt(n);
    for (rg int i = 1; i < n; ++i) {
        u = gi(), v = gi();
        insert(u, v), insert(v, u);
    }
    for (rg int i = 1; i <= n; ++i) val[i] = gi();
    dfs(1, 0);
    for (rg int i = 1; i <= tot; ++i) sort(bl[i].begin(), bl[i].end());
    m = gi();
    for (rg int i = 1; i <= m; ++i) {
        op = gi(), u = gi(), v = gi();
        u ^= ans, v ^= ans;
        if (!op) printf("%d\n", ans = query(u, v));
        else if (op == 1) change(u, v);
        else add(u, v);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hlw1/p/12285817.html