线段树合并模板求调【马蜂良好】
  • 板块学术版
  • 楼主AchorX
  • 当前回复6
  • 已保存回复6
  • 发布时间2024/1/2 11:06
  • 上次更新2024/1/2 17:23:25
查看原帖
线段树合并模板求调【马蜂良好】
763398
AchorX楼主2024/1/2 11:06
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 3;
int n, a[N], b[N], head[N << 1], len, rt[N];
struct Edge {
	int to, nxt;
} e[N << 1];
int ls[N * 18], rs[N * 18], sum[N * 18], num;
void In(int u, int v) {
	e[++len] = {v, head[u]};
	head[u] = len;
}
void update(int &p, int l, int r, int pos) {
	if (!p) p = ++num;
	if (l == r) {
		sum[p]++;
		return ;
	}
	int mid = (l + r) >> 1;
	if (pos <= mid) update(ls[p], l, mid, pos);
	else update(rs[p], mid + 1, r, pos);
	sum[p] = sum[ls[p]] + sum[rs[p]];
}
int modi(int p, int q, int l, int r) {
	if (!p || !q) return p + q;
	if (l == r) {
		sum[p] += sum[q];
		return p;
	}
	int mid = (l + r) >> 1;
	ls[p] = modi(ls[p], ls[q], l, mid);
	rs[p] = modi(rs[p], rs[q], mid + 1, r);
	sum[p] = sum[ls[p]] + sum[rs[p]];
	return p;
}
int ask(int p, int s, int t, int l, int r) {
	if (!p) return 0;
	if (l <= s && t <= r) return sum[p];
	int mid = (s + t) >> 1, tot = 0;
	if (l <= mid) tot += ask(ls[p], s, mid, l, r);
	if (r > mid) tot += ask(rs[p], mid + 1, t, l, r);
	return tot;
}
int ans[N];
void dfs(int u, int fa) {
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if (v == fa) continue;
		dfs(v, u);
		rt[u] = modi(rt[u], rt[v], 1, n);
	}
	ans[u] = ask(rt[u], a[u] + 1, n, 1, n);
}
void read() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), b[i] = a[i];
	sort(b + 1, b + n + 1);
	for (int i = 1; i <= n; ++i) {
		a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
		rt[i] = ++num;
		update(rt[i], 1, n, a[i]);
	}
	for (int i = 2, v; i <= n; ++i) {
		scanf("%d", &v);
		In(v, i), In(i, v);
	}
	dfs(1, 0);
	for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]);
}
int main() {
	read();
	return 0;
}
2024/1/2 11:06
加载中...