记录编号 |
89071 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[ZJOI 2004] 树的果实 |
最终得分 |
100 |
用户昵称 |
cstdio |
是否通过 |
通过 |
代码语言 |
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;
- }