P3605 [USACO17JAN]Promotion Counting P

线段树合并裸题。线段树的下标维护的是能力指数,需要离散化。统计答案可以在线段树上查询后缀和。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 1e5 + 100;
struct Edge {
	int v, nxt;
} e[N << 1];
struct Node {
	int lc, rc;
	int v;
} tr[N * 21];
vector<int> vec;
int a[N], n, m, cnt, idx, ans[N], head[N], root[N]; 

int get(int x) {
	return lower_bound(vec.begin(), vec.end(), x) - vec.begin(); 
}

void Add(int u, int v) {
	e[++cnt].v = v;
	e[cnt].nxt = head[u];
	head[u] = cnt;
} 

void pushup(int u) {
	tr[u].v = tr[tr[u].lc].v + tr[tr[u].rc].v;
}

void insert(int u, int l, int r, int k, int v) {
	if( l == r) {
		tr[u].v += v;
		return;
	}
	int mid = l + r >> 1;
	if(k <= mid) {
		if( !tr[u].lc)	tr[u].lc = ++ idx;
		insert(tr[u].lc, l, mid, k, v);
	}
	else {
		if( !tr[u].rc)  tr[u].rc = ++ idx;
		insert(tr[u].rc, mid + 1, r, k, v);
	}
	pushup(u);
} 

int query(int u, int l, int r, int k) {//查询后缀和  
	if( l >= k) {
		return tr[u].v;
	}
	int mid = l + r >> 1;
	int res = 0;
	if( k <= mid) {
		if(tr[u].lc)
			res += query(tr[u].lc, l, mid, k);
	}
	if( tr[u].rc)
		res += query(tr[u].rc, mid + 1, r, k);
	return res;
}

int merge(int p, int q, int l, int r) {
	if( !p || !q)
		return p + q;
	if( l == r) {
		tr[p].v += tr[q].v;
		return p;
	}
	int mid = l + r >> 1;
	tr[p].lc = merge(tr[p].lc, tr[q].lc, l, mid);
	tr[p].rc = merge(tr[p].rc, tr[q].rc, mid + 1, r);
	pushup(p);
	return p;
} 

void dfs(int u) {
	for(int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		dfs(v);
		root[u] = merge(root[u], root[v], 1, (int)vec.size());
	}
	ans[u] = query(root[u], 1, (int)vec.size(), a[u]) - 1;
} 

int main()
{
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++)
		root[i] = i;
	idx = n;
	for(int i = 1; i <= n; i ++) {
		scanf("%d", &a[i]);
		vec.push_back(a[i]);
	}
	sort(vec.begin(), vec.end());
	vec.erase(unique(vec.begin(), vec.end()), vec.end());
	for(int i = 1; i <= n; i ++) {
		a[i] = get(a[i]) + 1;
		insert(root[i], 1, (int)vec.size(), a[i], 1);
	}
	for(int i = 2; i <= n; i ++) {
		int x; 
		scanf("%d", &x);
		Add(x, i);
	}
	dfs(1);
	for(int i = 1; i <= n; i ++)
	    printf("%d\n", ans[i]);
	return 0;
} 
posted @ 2020-10-06 14:16  王雨阳  阅读(86)  评论(0编辑  收藏  举报