[loj3052]春节十二响

首先可以发现对于两条链来说,显然是对两边都排好序,然后大的配大的,小的配小的(正确性比较显然),最后再加入根(根只能单独选)
这个结果其实也可以理解为将所有max构成一条新的链,求出
因此,对于每一个结点计算出答案,然后与别的点合并得到父亲,用启发式合并+set时间复杂度为两个log。

 1 #include
 2 using namespace std;
 3 #define N 200005
 4 struct ji{
 5     int nex,to;
 6 }edge[N];
 7 priority_queue<int>qq,q[N];
 8 int E,n,x,y,a[N],f[N],head[N];
 9 long long ans;
10 void add(int x,int y){
11     edge[E].nex=head[x];
12     edge[E].to=y;
13     head[x]=E++;
14 }
15 int top(priority_queue<int>&q){
16     int k=q.top();
17     q.pop();
18     return k;
19 }
20 void dfs(int k){
21     for(int i=head[k];i!=-1;i=edge[i].nex){
22         int v=edge[i].to;
23         dfs(v);
24         if (q[f[k]].size()<q[f[v]].size())swap(f[k],f[v]);
25         while (!q[f[v]].empty())
26             qq.push(max(top(q[f[k]]),top(q[f[v]])));
27         while (!qq.empty())q[f[k]].push(top(qq));
28     }
29     q[f[k]].push(a[k]);
30 }
31 int main(){
32     scanf("%d",&n);
33     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
34     for(int i=1;i<=n;i++)f[i]=i;
35     memset(head,-1,sizeof(head));
36     for(int i=2;i<=n;i++){
37         scanf("%d",&x);
38         add(x,i);
39     }
40     dfs(1);
41     while (!q[f[1]].empty())ans+=top(q[f[1]]);
42     printf("%lld",ans);
43 }
View Code

 

你可能感兴趣的:([loj3052]春节十二响)