P3605 [USACO17JAN]Promotion Counting P 题解

solution

考虑权值线段树合并:首先离散化,然后对于一个节点,我们将它的所有子树合并上来,并统计所有能力指数的个数(权值线段树基本操作),查询时只需查询 \(p_i+1\sim n\) 的和即可

code

#include <bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define I inline
#define ll long long
#define CI const int
#define RI register int
#define W while
#define gc getchar
#define D isdigit(c=gc())
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define ms(a,x) memset((a),(x),sizeof(a))
using namespace std;
namespace SlowIO {
	I void readc (char& c) {W (isspace (c = gc ()));}
	Tp I void read (Ty& x) {char c; int f = 1; x = 0; W (! D) f = c ^ '-' ? 1 : -1; W (x = (x * 10) + (c ^ 48), D); x *= f;}
	Ts I void read (Ty& x, Ar&... y) {read (x); read (y...);}
} using namespace SlowIO;
CI N = 1e5, N2 = 2e5, N4 = 5e6; int sum[N4 + 5], tg[N4 + 5], sl[N4 + 5], sr[N4 + 5], a[N + 5], lsh[N + 5], anss[N + 5], rt[N + 5], ntot = 0, tot, n;
namespace graph {
	int nxt[N2 + 5], to[N2 + 5], hd[N + 5], cnt = 0;
	void add (int u, int v) {++ cnt; to[cnt] = v; nxt[cnt] = hd[u]; hd[u] = cnt;}
} using namespace graph;
void pushup (int root) {sum[root] = sum[sl[root]] + sum[sr[root]];}
void update (int &root, int L, int R, int pos) {
	if (! root) root = ++ ntot; if (L == R) {++ sum[root]; tg[root] = L; return ;} int mid = (L + R) >> 1;
	if (pos <= mid) update (sl[root], L, mid, pos); else update (sr[root], mid + 1, R, pos); pushup (root);
}
int merge (int a, int b, int L, int R) {
	if (! a || ! b) return a + b; if (L == R) {sum[a] += sum[b]; tg[a] = tg[b]; return a;} int mid = (L + R) >> 1;
	sl[a] = merge (sl[a], sl[b], L, mid); sr[a] = merge (sr[a], sr[b], mid + 1, R); pushup (a); return a;
}
int query (int root, int L, int R, int x, int y) {
	if (L >= x && R <= y) return sum[root]; if (R < x || L > y) return 0; int mid = (L + R) >> 1, s = 0;
	if (x <= mid) s += query (sl[root], L, mid, x, y); if (y > mid) s += query (sr[root], mid + 1, R, x, y); return s;
}
void dfs (int now, int fa) {
	RI i, j; for (i = hd[now]; i; i = nxt[i]) {if (to[i] == fa) continue; dfs (to[i], now); rt[now] = merge (rt[now], rt[to[i]], 1, tot); } update (rt[now], 1, tot, a[now]);
	anss[now] = query (rt[now], 1, tot, a[now] + 1, tot);
}
int main () {
	RI i, j; for (read (n), i = 1; i <= n; ++ i) read (a[i]), lsh[i] = a[i]; sort (lsh + 1, lsh + n + 1); tot = unique (lsh + 1, lsh + n + 1) - lsh - 1;
	for (i = 1; i <= n; ++ i) a[i] = lower_bound (lsh + 1, lsh + tot + 1, a[i]) - lsh; for (i = 2; i <= n; ++ i) {int x; read (x); add (i, x); add (x, i);} dfs (1, 0);
	for (i = 1; i <= n; ++ i) printf ("%d\n", anss[i]);
	return 0;
}
posted @ 2022-08-21 22:54  ClapEcho233  阅读(17)  评论(0编辑  收藏  举报