记录编号 89071 评测结果 AAAAAAAAAA
题目名称 [ZJOI 2004] 树的果实 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 1.485 s
提交时间 2014-02-28 14:48:20 内存使用 5.28 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<map>
using namespace std;
const int SIZEN=100100;
int N;
int father[SIZEN]={0};
vector<int> c[SIZEN];//儿子
int delic[SIZEN]={0};//美味值
int numpst[SIZEN]={0};//子树上节点个数
int A[SIZEN]={0},B[SIZEN]={0},C[SIZEN]={0};//分别对应三个答案
//即:上面部分(子树),下面部分(除了子树),树根到该点路径中更美味的果子个数
map<int,int> dlcmp;//离散化后的美味值
int numval;//不同美味值的个数
int dfn[SIZEN]={0};//时间戳
class TARRAY{//树状数组
public:
	int n;//范围1~n
	int s[SIZEN];
	void clear(int x){memset(s,0,sizeof(s)),n=x;}
	int lowbit(int x){return x&(-x);}
	int prefsum(int x){//前缀和
		int ans=0;
		for(int i=x;i>0;i-=lowbit(i)) ans+=s[i];
		return ans;
	}
	int segsum(int x,int y){//区间[x,y]的和
		if(x>y) return 0;
		return prefsum(y)-prefsum(x-1);
	}
	void change(int x,int t){//第x个元素+t
		for(int i=x;i<=n;i+=lowbit(i)) s[i]+=t;
	}
};
TARRAY tree;//树状数组
pair<int,int> sorted[SIZEN];//first是美味值,second是位置
void work(void){
	tree.clear(N);
	for(int i=1;i<=N;i++) sorted[i]=make_pair(delic[i],i);
	sort(sorted+1,sorted+1+N);
	for(int i=N;i>=1;){
		int j;
		for(j=i;sorted[j].first==sorted[i].first;j--){
			int x=sorted[j].second;
			A[x]=tree.segsum(dfn[x],dfn[x]+numpst[x]-1);
			B[x]=tree.segsum(1,N)-A[x];
		}
		for(;i>j;i--) tree.change(dfn[sorted[i].second],1);
	}
}
int tim=0;//时间
void DFS(int x){
	tim++;
	dfn[x]=tim;
	C[x]=tree.segsum(delic[x]+1,numval);
	tree.change(delic[x],1);
	numpst[x]=1;//子树上节点个数
	for(int i=0;i<c[x].size();i++){
		DFS(c[x][i]);
		numpst[x]+=numpst[c[x][i]];
	}
	tree.change(delic[x],-1);
}
void init(void){
	scanf("%d",&N);
	for(int i=2;i<=N;i++){
		scanf("%d",&father[i]);
		c[father[i]].push_back(i);
	}
	vector<int> atp;
	for(int i=1;i<=N;i++) scanf("%d",&delic[i]),atp.push_back(delic[i]);
	sort(atp.begin(),atp.end());
	numval=0;
	for(int i=0;i<atp.size();i++) if(!i||atp[i]!=atp[i-1]) dlcmp[atp[i]]=++numval;//离散化
	for(int i=1;i<=N;i++) delic[i]=dlcmp[delic[i]];//修改美味值
	tree.clear(numval);//以权值为下标的树状数组
}
int main(){
	freopen("treesfruits.in","r",stdin);
	freopen("treesfruits.out","w",stdout);
	init();
	DFS(1);
	work();
	for(int i=1;i<=N;i++) printf("%d %d %d\n",A[i],B[i],C[i]);
	return 0;
}