题面
题解
首先这是一道树上区间第k大的问题, 他求的是第k小, 转换一下就行
1、树剖+线段树套平衡树,查询时需要二分答案, 代码200行就出去了, 还是4个logn卡过去的
2、树剖+动态主席树(或者Kruskal重构树?),省去了2分, 3logn, 代码也是200+
3、作为个懒狗, 菜鸡这种200+的实在不友好, 复杂度也不友好
不管结构的话, 就是一个 动态第k大, 动态主席树秒了
然而这是颗树, 就有了树剖的logn
树剖有的dfs序是很巧妙的, 子树的序号是连续的
每次修改只影响子树, 而子树的编号又是连续的~
那我们就可以修改的时候是个区间修改!(当然先跑出来dfs序)
正好动态主席树就是树状(线段树维护的), 支持区间修改!
剩下的迎刃而解
什么你不知道怎么树上算值域个数?
在值域[l, r], (s, t)上的个数为, (root, s) + (root, t) - (root, lca(s, t)) - (root, father[lca(s, t)]);
2个优美的log, 收工
代码
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n) * (n)
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 8e4 + 5;
struct STFrom {
static const int N = 8e4 + 5;
int f[N][20], dep[N], t;
int *h, *ne, *to;
void init(int n, int* H, int* Ne, int* To) {
t = log2(n - 1) + 1;
h = H, ne = Ne, to = To;
}
void bfs(int s) {
queue<int> q;
q.push(s); dep[s] = 1;
rep (i, 0, t) f[s][i] = 0;
while (!q.empty()) {
int x = q.front(); q.pop();
for (int i = h[x]; i; i = ne[i]) {
int y = to[i];
if (dep[y]) continue;
dep[y] = dep[x] + 1;
f[y][0] = x;
for (int j = 1; j <= t; ++j)
f[y][j] = f[f[y][j - 1]][j - 1];
q.push(y);
}
}
}
int lca(int x, int y) {
if (dep[x] > dep[y]) swap(x, y);
per (i, t, 0) if (dep[f[y][i]] >= dep[x]) y = f[y][i];
if (x == y) return x;
per (i, t, 0)
if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][0];
}
int dist(int x, int y) {
return dep[x] + dep[y] - (dep[lca(x, y)] << 1);
}
} ST;
struct CHT {
static const int M = 6e7;
struct node {
int val, lson, rson; /*int l, r; 值域*/
node (int Val = 0, int Ls = 0, int Rs = 0)
: val(Val), lson(Ls), rson(Rs){}
} tr[N * 520]; //log2(sz)*log2(sz)*n
int root[N], tot, qsc, qtc, quc, qwc, sz, n; // n为数组大小,sc为值域
int qs[15], qt[15], qu[15], qw[15]; //log(n)
void build(int n, int sz, int *a, PII *dfn) {
this->sz = sz; this->n = n;
for (int i = 1; i <= n; ++i)
change(dfn[i].fi, a[i], 1), change(dfn[i].se + 1, a[i], -1);
}
void update(int &rt, int l, int r, int k, int cnt) {
if (!rt) rt = ++tot;
tr[rt].val += cnt;
if (l == r) return;
int mid = l + r >> 1;
if (k <= mid) update(tr[rt].lson, l, mid, k, cnt);
else update(tr[rt].rson, mid + 1, r, k, cnt);
}
void change(int x, int k, int cnt) { //n为最大区间长度
for (int i = x; i <= n; i += i & -i)
update(root[i], 0, sz, k, cnt);
}
int ask(int l, int r, int k) {
if (l == r) return l;
int sum = 0;
for (int i = 1; i <= qsc; ++i) sum += tr[tr[qs[i]].lson].val;
for (int i = 1; i <= qtc; ++i) sum += tr[tr[qt[i]].lson].val;
for (int i = 1; i <= quc; ++i) sum -= tr[tr[qu[i]].lson].val;
for (int i = 1; i <= qwc; ++i) sum -= tr[tr[qw[i]].lson].val;
int mid = l + r >> 1;
if (sum >= k) {
for (int i = 1; i <= qsc; ++i) qs[i] = tr[qs[i]].lson;
for (int i = 1; i <= qtc; ++i) qt[i] = tr[qt[i]].lson;
for (int i = 1; i <= quc; ++i) qu[i] = tr[qu[i]].lson;
for (int i = 1; i <= qwc; ++i) qw[i] = tr[qw[i]].lson;
return ask(l, mid, k);
} else {
for (int i = 1; i <= qsc; ++i) qs[i] = tr[qs[i]].rson;
for (int i = 1; i <= qtc; ++i) qt[i] = tr[qt[i]].rson;
for (int i = 1; i <= quc; ++i) qu[i] = tr[qu[i]].rson;
for (int i = 1; i <= qwc; ++i) qw[i] = tr[qw[i]].rson;
return ask(mid + 1, r, k - sum);
}
}
int preask(int s, int t, int u, int w, int k) {
qtc = qsc = quc = qwc = 0;
for (int i = s; i; i -= -i & i) qs[++qsc] = root[i];
for (int i = t; i; i -= -i & i) qt[++qtc] = root[i];
for (int i = u; i; i -= -i & i) qu[++quc] = root[i];
for (int i = w; i; i -= -i & i) qw[++qwc] = root[i];
return ask(0, sz, k);
}
} bit;
int n, m, _, k;
int h[N], ne[N << 1], to[N << 1], tot;
int op[N], x[N], y[N];
int a[N], df;
PII dfn[N];
void add(int u, int v) {
ne[++tot] = h[u]; to[h[u] = tot] = v;
}
void dfs(int x, int f) {
dfn[x].fi = ++df;
for (int i = h[x]; i; i = ne[i]) {
int y = to[i];
if (y == f) continue;
dfs(y, x);
}
dfn[x].se = df;
}
int main() {
IOS; cin >> n >> m; VI c;
rep (i, 1, n) cin >> a[i], c.pb(a[i]);
rep (i, 2, n) {
int u, v; cin >> u >> v;
add(u, v); add(v, u);
}
rep (i, 1, m) {
cin >> op[i] >> x[i] >> y[i];
if (!op[i]) c.pb(y[i]);
}
sort(all(c)); c.erase(unique(all(c)), c.end());
rep (i, 1, n) a[i] = lower_bound(all(c), a[i]) - c.begin();
rep (i, 1, m) if (!op[i]) y[i] = lower_bound(all(c), y[i]) - c.begin();
ST.init(n, h, ne, to); ST.bfs(1);
dfs(1, 0); bit.build(n, c.size(), a, dfn);
rep (i, 1, m) {
if (!op[i]) {
bit.change(dfn[x[i]].fi, a[x[i]], -1);
bit.change(dfn[x[i]].se + 1, a[x[i]], 1);
a[x[i]] = y[i];
bit.change(dfn[x[i]].fi, a[x[i]], 1);
bit.change(dfn[x[i]].se + 1, a[x[i]], -1);
} else {
int k = ST.dist(x[i], y[i]) + 2 - op[i], lca = ST.lca(x[i], y[i]);
if (k <= 0) cout << "invalid request!
";
else cout << c[bit.preask(dfn[x[i]].fi, dfn[y[i]].fi,
dfn[lca].fi, dfn[ST.f[lca][0]].fi, k)] << '
';
}
}
return 0;
}