https://csustacm.fun/problem/2033
这个题目还是比较简单的,但是比赛的时候没有像清楚,用了一个不太熟悉的数据结构主席树,
所以出现了bug,主席树的bug是真的难找。
这个题目就是首先用dfs+线段树求出每一个富翁的val
然后用二分加线段树来找位置。
#include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm> #include <iostream> #define inf 0x3f3f3f3f using namespace std; const int maxn = 1e5 + 10; typedef long long ll; ll a[maxn], lazy[maxn * 4], sum[maxn * 4], flag[maxn * 4]; int n, val[maxn]; vector<int>G[maxn]; void add(int u, int v) { G[u].push_back(v); G[v].push_back(u); } void push_down(int id,int l,int r) { if (lazy[id] == 0) return; // printf("ss id=%d l=%d r=%d ", id, l, r); int mid = (l + r) >> 1; if (flag[id << 1]) { // printf("id=%d l=%d r=%d ", id, l, r); sum[id << 1] += (mid - l + 1)*lazy[id]; lazy[id << 1] += lazy[id]; } if (flag[id << 1 | 1]) { // printf("ww id=%d l=%d r=%d ", id, l, r); sum[id << 1 | 1] += (r - mid)*lazy[id]; lazy[id << 1 | 1] += lazy[id]; } lazy[id] = 0; } void update1(int id, int l, int r, int pos,int f) { if (pos<l || pos>r) return; if (f == 0) flag[id]++; else if (f == 1)flag[id]--; if (l == r) { sum[id] = 1; return; } push_down(id, l, r); int mid = (l + r) >> 1; if (pos <= mid) update1(id << 1, l, mid, pos, f); else update1(id << 1 | 1, mid + 1, r, pos, f); sum[id] = sum[id << 1] + sum[id << 1 | 1]; } void update2(int id,int l,int r,int x,int y) { // printf("id=%d l=%d r=%d x=%d y=%d ", id, l, r, x, y); if (x > r || y < l) return; if (x <= l && y >= r) { lazy[id] += 1; sum[id] += (r - l + 1); return; } push_down(id, l, r); int mid = (l + r) >> 1; if (x <= mid) update2(id << 1, l, mid, x, y); if (y > mid) update2(id << 1 | 1, mid + 1, r, x, y); sum[id] = sum[id << 1] + sum[id << 1 | 1]; } int query(int id,int l,int r,int pos) { if (pos<l || pos>r) return 0; if (l == r) return sum[id]; push_down(id, l, r); int mid = (l + r) >> 1; if (pos <= mid) return query(id << 1, l, mid, pos); return query(id << 1 | 1, mid + 1, r, pos); } void dfs(int u, int pre) { // printf("u=%d a=%lld ", u, a[u]); update2(1, 1, n, 1, a[u]); update1(1, 1, n, a[u], 0); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (v == pre) continue; dfs(v, u); val[a[u]] = min(val[a[u]], query(1, 1, n, a[u])); // printf("val[%lld]=%d v=%d ", a[u], val[a[u]], v); update1(1, 1, n, a[u], 2); } update1(1, 1, n, a[u], 1); } int c[maxn]; int lowbit(int x) { return x & (-x); } void update(int x,int k) { while (x <= n) { c[x] += k; x += lowbit(x); } } int getsum(int x) { int ans = 0; while (x > 0) { ans += c[x]; x -= lowbit(x); } return ans; } int main() { int x; scanf("%d", &n); memset(val, inf, sizeof(val)); for (int i = 1; i <= n; i++) scanf("%d", &x), a[x] = i, G[i].clear(); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v); } dfs(1, -1); for (int i = 1; i <= n; i++) if (val[i] >= inf) val[i] = 1; // for (int i = 1; i <= n; i++) printf("val[%d]=%d ", i, val[i]); for (int i = 1; i <= n; i++) { int l = 1, r = n, ans = 0; while (l <= r) { int mid = (l + r) >> 1; int res = mid - getsum(mid); if (res >= val[i]) ans = mid, r = mid - 1; else l = mid + 1; } printf("%d ", ans); update(ans, 1); } return 0; }