Split The Tree
阿新 • • 發佈:2018-09-05
delet gif opera arc names traints 題目 pac span
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.
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
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 wiWe 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.
輸入
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> #defineView CodeN 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; }
Split The Tree