洛谷 P3605 [USACO17JAN]Promotion Counting P

-----

题链

--解法一

跑一边dfs序,按照权值大小对n个点从大到小排好遍历,对于第i个点只要求它子树的和就行;

#include <bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define PI acos(-1.0)
#define eps 1e-8
#define Pair pair<double,double>
// notice
#define mod 998244353 
#define MAXN 1e18
#define MS 100009

LL n,m;
struct node{
	LL val,id;
}a[MS];
LL b[MS],tb;
LL dfn[MS];
LL sz[MS];
vector<LL > vc[MS];
LL p[MS];
queue<LL > Q;
LL ac[MS];
LL tot;

bool cmp(node t1,node t2){
	return t1.val > t2.val;
}

LL lowbit(LL x){
	return x&(-x);
}

void add(LL pos,LL val){
	for(;pos<=n;pos+=lowbit(pos)) p[pos] += val;
}

LL query(LL pos){
	LL ans = 0;
	for(;pos;pos-=lowbit(pos)) ans += p[pos];
	return ans;
}

void dfs(LL x){
	dfn[x] = ++tot;
	sz[x] = 1;
	for(auto &i:vc[x]){
		dfs(i);
		sz[x] += sz[i];
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i].val;
		a[i].id = i;
		b[i] = a[i].val;
	}
	sort(b+1,b+n+1);
	tb = 1;
	for(int i=2;i<=n;i++){
		if(b[i] != b[i-1]) b[++tb] = b[i];
	}
	for(int i=1;i<=n;i++){
		a[i].val = lower_bound(b+1,b+tb+1,a[i].val) - b;
	}
	sort(a+1,a+n+1,cmp);
	
	for(int i=2;i<=n;i++){
		LL x;
		cin >> x;
		vc[x].push_back(i);
	}
	
	dfs(1);
	
	for(int i=1;i<=n;i++){
		node t = a[i];
		LL tl = dfn[t.id];
		LL tr = tl+sz[t.id]-1;
		LL ans = query(tr) - query(tl);
		ac[t.id] = ans;
		add(dfn[t.id],1);
	}
	
	for(int i=1;i<=n;i++){
		cout << ac[i] << "\n";
	}
	

	return 0;
}

--解法二

离散化+树状数组,dfs求解;

dfs时,每碰到一个点就将它的权值记录在树状数组中,此时会有一个问题,有两颗子树互不影响,记两颗子树的头节点为t1,t2,dfs时会先遍历第一颗子树,此时到第二颗时,显然第二颗也就是t2的答案应该与之前维护的权值无关,此时可以两眼一闭查一下树状数组中比t2大的个数,然后把t2的子节点全部遍历完后再查一次比t2大的个数,两次的差值就是t2的答案;

#include <bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define PI acos(-1.0)
#define eps 1e-8
#define Pair pair<double,double>
// notice
#define mod 998244353 
#define MAXN 1e18
#define MS 100009

LL n,m;
LL a[MS];
LL b[MS],tb;
vector<LL > vc[MS];
LL p[MS];
LL ac[MS];

LL lowbit(LL x){
	return x&(-x);
} 

void add(LL pos,LL val){
	for(;pos<=n;pos+=lowbit(pos)) p[pos] += val;
}

LL query(LL pos){
	LL ans = 0;
	for(;pos;pos-=lowbit(pos)) ans += p[pos];
	return ans;
}

void dfs(LL x){
	ac[x] = -(query(n) - query(a[x]));
	for(auto &i:vc[x]){
		dfs(i);
	}
	ac[x] += query(n) - query(a[x]);
	add(a[x],1);
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		b[i] = a[i];
	}
	sort(b+1,b+n+1);
	tb = 1;
	for(int i=2;i<=n;i++){
		if(b[i] != b[i-1]) b[++tb] = b[i];
	}
	for(int i=1;i<=n;i++){
		a[i] = lower_bound(b+1,b+tb+1,a[i]) - b;
	}
	
	for(int i=2;i<=n;i++){
		LL x;
		cin >> x;
		vc[x].push_back(i);
	}
	
	dfs(1);
	
	for(int i=1;i<=n;i++){
		cout << ac[i] << "\n";
	}

	return 0;
}

posted @ 2021-06-03 22:15  棉被sunlie  阅读(50)  评论(0)    收藏  举报