bzoj1146
树链剖分+二分+线段树套treap
写题5分钟,调试2小时。。。
很好理解,就是维护树链剖分的线段树改成线段树套treap,然后每次树套树删除一个数,插入一个数,二分一个数查找排名就行了
#include<bits/stdc++.h> using namespace std; const int N = 100010, M = 19992147; inline int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } int n, q; int t[N]; vector<int> G[N]; struct Treap { int seed, cnt; int child[N * 50][2], tot[N * 50], key[N * 50], p[N * 50], size[N * 50]; int rand() { seed = abs(seed * M + 12345); return seed; } void update(int x) { size[x] = size[child[x][0]] + size[child[x][1]] + tot[x]; } void rotate(int &x, int t) { int y = child[x][t]; child[x][t] = child[y][t ^ 1]; child[y][t ^ 1] = x; update(x); update(y); x = y; } void insert(int &x, int val) { if(x == 0) { p[x = ++cnt] = rand(); key[x] = val; tot[x] = 1; update(x); } else { if(key[x] == val) { ++tot[x]; update(x); return; } int t = val > key[x]; insert(child[x][t], val); if(p[child[x][t]] > p[x]) rotate(x, t); update(x); } } void erase(int &x, int val) { if(key[x] == val) { if(child[x][0] == 0 && child[x][1] == 0) { --tot[x]; if(tot[x] == 0) x = 0; else update(x); return; } int t = p[child[x][0]] < p[child[x][1]]; rotate(x, t); erase(child[x][t ^ 1], val); } else erase(child[x][val > key[x]], val); update(x); } int query(int x, int val) { if(x == 0) return 0; // printf("key[%d]=%d val=%d\n", x, key[x], val); if(val == key[x]) return size[child[x][1]]; if(val < key[x]) return size[child[x][1]] + tot[x] + query(child[x][0], val); return query(child[x][1], val); } } treap; namespace seg { int root[N << 2], mir[N]; void build(int l, int r, int x) { for(int i = l; i <= r; ++i) treap.insert(root[x], t[mir[i]]); if(l == r) return; int mid = (l + r) >> 1; build(l, mid, x << 1); build(mid + 1, r, x << 1 | 1); } void update(int l, int r, int x, int pos, int pre, int now) { treap.erase(root[x], pre); treap.insert(root[x], now); if(l == r) return; int mid = (l + r) >> 1; if(pos <= mid) update(l, mid, x << 1, pos, pre, now); else update(mid + 1, r, x << 1 | 1, pos, pre, now); } int query(int l, int r, int x, int a, int b, int k) { if(l > b || r < a) return 0; if(l >= a && r <= b) return treap.query(root[x], k); int mid = (l + r) >> 1; return (query(l, mid, x << 1, a, b, k) + query(mid + 1, r, x << 1 | 1, a, b, k)); } } using namespace seg; namespace heavy_light_decomposition { int dfs_clock; int dfn[N], top[N], fa[N], dep[N], size[N], son[N]; void dfs(int u, int last) { size[u] = 1; for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == last) continue; dep[v] = dep[u] + 1; fa[v] = u; dfs(v, u); size[u] += size[v]; if(size[v] > size[son[u]]) son[u] = v; } } void dfs(int u, int last, int acs) { dfn[u] = ++dfs_clock; mir[dfs_clock] = u; top[u] = acs; if(son[u]) dfs(son[u], u, acs); for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == last || v == son[u]) continue; dfs(v, u, v); } } void change(int a, int b) { update(1, n, 1, dfn[a], t[a], b); t[a] = b; } int lca(int u, int v) { while(top[u] != top[v]) { if(dep[top[u]] < dep[top[v]]) swap(u, v); u = fa[top[u]]; } return dep[u] < dep[v] ? u : v; } int dis(int u, int v) { int x = lca(u, v); return dep[u] + dep[v] - 2 * dep[x] + 1; } int check(int mid, int u, int v) { int ret = 0; while(top[u] != top[v]) { if(dep[top[u]] < dep[top[v]]) swap(u, v); ret += query(1, n, 1, dfn[top[u]], dfn[u], mid); u = fa[top[u]]; } if(dep[u] < dep[v]) swap(u, v); ret += query(1, n, 1, dfn[v], dfn[u], mid); return ret + 1; } void ask(int k, int u, int v) { int l = 0, r = 100000010, ans = 0; if(dis(u, v) < k) { puts("invalid request!"); return; } while(r - l > 1) { int mid = (l + r) >> 1, x = check(mid, u, v); // printf("mid=%d x=%d\n", mid, x); if(check(mid, u, v) > k) l = mid; else r = ans = mid; } printf("%d\n", ans); } } using namespace heavy_light_decomposition; int main() { n = read(); q = read(); for(int i = 1; i <= n; ++i) t[i] = read(); for(int i = 1; i < n; ++i) { int u = read(), v = read(); G[u].push_back(v); G[v].push_back(u); } dfs(1, 0); dfs(1, 0, 1); build(1, n, 1); while(q--) { int opt, x, y; scanf("%d%d%d", &opt, &x, &y); if(opt == 0) change(x, y); else ask(opt, x, y); } return 0; }