维护初始有 \(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\)
显然可以用分块做,也可以用主席树来做,但是第三个操作不好处理。
简单的树上分块会被菊花图卡,所以我被卡了。。。。。。
卡常 + 吸氧 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;
}
原文:https://www.cnblogs.com/hlw1/p/12285817.html