1. 程式人生 > >Split The Tree

Split The Tree

delet gif opera arc names traints 題目 pac span

Split The Tree

時間限制: 1 Sec 內存限制: 128 MB

題目描述

You are given a tree with n vertices, numbered from 1 to n. ith vertex has a value wi
We define the weight of a tree as the number of different vertex value in the tree.
If we delete one edge in the tree, the tree will split into two trees. The score is the sum of these two trees’ weights.
We want the know the maximal score we can get if we delete the edge optimally.

輸入

Input is given from Standard Input in the following format:
n
p2 p3 . . . pn
w1 w2 . . . wn
Constraints
2 ≤ n ≤ 100000 ,1 ≤ pi < i
1 ≤ wi ≤ 100000(1 ≤ i ≤ n), and they are integers
pi means there is a edge between pi and i

輸出

Print one number denotes the maximal score.

樣例輸入

3
1 1
1 2 2

樣例輸出

3

來源/分類

2018東北四省賽


題意:每顆樹的重量定義為這顆樹上所有節點權值不同的個數,現在要割掉一條邊,求生成的兩顆樹最大的重量和。

做法:dfs序,然後枚舉每一條邊,刪除這條邊就相當於在dfs序中取走了一個區間,問題就變成了求區間不同數的個數。取走一個區間後,剩下的兩塊區間求不同數個數可以通過把區間加長一倍來做。

技術分享圖片
#include<bits/stdc++.h>
#define
N 100050 using namespace std; vector<int>edge[N]; int w[N]; int children[N]={0},number[N]={0},dfsorder[N],len=0; int dfs(int x) { dfsorder[++len]=x; number[x]=len; children[x]=1; int Size=edge[x].size(); for(int i=0;i<Size;i++) if(number[edge[x][i]]==0) { children[x]+=dfs(edge[x][i]); } return children[x]; } struct ss { int l,r,index,ans; bool operator < (const ss& s) const { return r<s.r; } }; vector<ss>interval; int c[2*N+5]={0}; void updata(int x,int v) { for(int i=x;i<2*N;i+=i&(-i))c[i]+=v; } int Sum(int x) { int ans=0; while(x>0) { ans+=c[x]; x-=x&(-x); } return ans; } int main() { int n; scanf("%d",&n); for(int i=2;i<=n;i++) { int p; scanf("%d",&p); edge[i].push_back(p); edge[p].push_back(i); } for(int i=1;i<=n;i++)scanf("%d",&w[i]); dfs(1); for(int i=1;i<=n;i++) { interval.push_back((ss){number[i],number[i]+children[i]-1,i,0}); interval.push_back((ss){number[i]+children[i],n+number[i]-1,i,0}); } for(int i=1;i<=n;i++) { dfsorder[i]=w[dfsorder[i]]; dfsorder[n+i]=dfsorder[i]; } sort(interval.begin(),interval.end()); int last[N]={0}; int c1=1; for(int i=0;i<2*n;i++) { if(interval[i].l>interval[i].r)continue; for(int j=c1;j<=interval[i].r;j++) { if(last[dfsorder[j]]==0) { updata(j,1); last[dfsorder[j]]=j; } else { updata(last[dfsorder[j]],-1); updata(j,1); last[dfsorder[j]]=j; } } interval[i].ans=Sum(interval[i].r)-Sum(interval[i].l-1); c1=interval[i].r+1; } int sum[N]={0},ans=0; for(int i=0;i<2*n;i++) { sum[interval[i].index]+=interval[i].ans; ans=max(ans,sum[interval[i].index]); } printf("%d\n",ans); return 0; }
View Code

Split The Tree