[loj3052]春节十二响

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

 1 #include<bits/stdc++.h>
 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 }

原文地址:https://www.cnblogs.com/PYWBKTDA/p/11620949.html

时间: 2024-08-11 19:26:01

[loj3052]春节十二响的相关文章

[十二省联考2019]春节十二响

好后悔考场没思考这道最良心的水题...t1花了我两个半点结果连20都拿不到 哭了 题目描述:略 思路:将一个点下面的几条链合并成一条 用长链剖分的话似乎可以简化操作 实在太水了所以没啥好说的... 1 #include<cstdio> 2 #include<queue> 3 using std::priority_queue; 4 typedef long long lint; 5 const int N=200011; 6 template<typename st>

bzoj 5499: [2019省队联测]春节十二响【堆】

首先看两条链怎么合并,贪心可得是从大到小取max,多条链同理 所以dfs合并子树的大根堆即可,注意为了保证复杂度,合并的时候要合并到最长链上,证明见长链剖分 #include<iostream> #include<cstdio> #include<queue> using namespace std; const int N=200005; int n,a[N],h[N],cnt,id[N],tot,p[N]; long long ans; priority_queue

P5290 [十二省联考2019]春节十二响

题目链接 题意分析 首先考虑链的话 就是将\(1\)部分的两条子链排序之后 贪心合并即可 那么考虑树的话 我们照样合并就行了 首先 排序的话 我们使用堆就可以了 然后 涉及到了两点问题 \(1.\)我们对于\(u\)以及\(v\)这两个维护好的堆合并的话 为了保证时间复杂度 我们需要使用启发式合并 \(2.\)我们由于启发式合并的话涉及到了交换两个堆的问题 听巨佬说 c++11的话 直接swap是\(O(1)\)的 否则的话 直接\(swap\)就是\(O(n)\) 所以我们考虑维护新的编号 然

[十二省联考2019]D2T2春节十二响

嘟嘟嘟 这题真没想到这么简单-- 首先有60分大礼:\(O(n ^ 2logn)\)贪心.(我也不知道为啥就是对的) 然后又送15分链:维护两个堆,每次去堆顶的最大值. 这时候得到75分已经很开心了,但其实离AC也就差一点点. 链的做法已经给了我们提示:合并两个堆.其实这就相当于二叉树.那多叉树呢?就合并多个堆呗!从子树向上递归的时候不断将子树启发式合并,复杂度就保证了. 代码真的很短 #include<cstdio> #include<iostream> #include<

[十二省联考]春节十二响

一个特殊的启发式合并 大概是sz(a)+sz(b)=sz(max(a,b)) 所以其实是一个log //Love and Freedom. #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> #define ll long long #define inf 20021225 #define N 200100 using nam

十二省联考

异或粽子: #include<iostream> #include<cstdio> #include<queue> using namespace std; typedef long long i64; const int N=7e5+5; const int D=64; const int S=N*D; int cnt,c[S][2],z[S]; i64 a[N],s[N]; int f[N]; struct inf{ i64 s; int x; bool opera

《Android源代码设计模式解析与实战》读书笔记(二十二)

第二十二章.享元模式 享元模式是结构型设计模式之中的一个.是对对象池的一种实现.就像它的名字一样,共享对象.避免反复的创建. 我们经常使用的String 就是使用了共享模式.所以String类型的对象创建后就不可改变,假设当两个String对象所包括的内容同样时,JVM仅仅创建一个String对象相应这两个不同的对象引用. 1.定义 採用一个共享来避免大量拥有同样内容对象的开销.使用享元模式可有效支持大量的细粒度对象. 2.使用场景 (1)系统中存在大量的类似对象. (2)细粒度的对象都具备较接

史玉柱身边的打工皇后十二年挣了5个亿 那些年我们走过的路(一年多不给公司结账,程晨接手后,从来不跟采购谈那个账款问题。而是下班后主动帮她接孩子,然后客户主动跟她结清了所有货款)

看看这位打工皇后,十二年挣了5个亿.1995年20岁的程晨从南京大学毕业加盟了巨人集团.当时巨人集团正好是史玉柱最辉煌的时候,当时产值10个亿,史玉柱被福布斯评为内地富豪第八名. 程晨从底层业务员起步,三个月转正,半年后升为业务主管.她勤奋上进,别人花8小时跑业务,她在8小时之外还与客户联络感情,不管什么区域什么客户都能提高业绩.!有一个商场客户,一年多不给公司结账,程晨接手后,从来不跟采购谈那个账款问题.而是下班后主动帮她接孩子,然后客户主动跟她结清了所有货款. 1996年3月,史玉柱到江苏,

第三十二章

道恒无名,朴虽小,而天下弗敢臣.侯王若能守之,万物将自宾.天地相合,以俞甘露,民莫之令而自均焉.始制有名,名亦既有,夫亦将知止,知止所以不殆.譬道之在天下也,犹小谷之与江海也. 第三十二章1 如何让大家都来顺服你? 各位朋友大家好,今天我们接着来聊<道德经>.今天我们不唱歌了,昨天放了一首我唱的歌,这唱歌在我这儿就是一个养生运动.因为唱歌的时候你要调呼吸,这时候是锻炼肺.我之前写过两篇文章,专门讲唱歌的,我们家有一位邻居.一位朋友,这肺间质性病变,很严重的肺病,结果人家天天唱歌,现在恢复的特别