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

题目链接

LOJ:https://loj.ac/problem/3052

洛谷:https://www.luogu.org/problemnew/show/P5290

BZOJ:https://www.lydsy.com/JudgeOnline/problem.php?id=5499

Solution

部分分有一个链的情况极大的提示了正解。

考虑链情况怎么做,显然是\(1\)号节点向下延伸出了两条支链,那么我们可以分别\(\rm sort\)然后最大的和最大的成对,次打的同理,这样显然是最优的。

那么我们考虑二叉树怎么做,同样对于点\(x\)我们开一个堆记录这个点的子树的使用信息,那么点\(x\)可以通过两个儿子按照链情况一样的合并得到。

普通的树同理,如果我们加一个启发式合并就可以做到\(O(n\log n)\)。

注意启发式合并的时候有一个\(\rm swap\)堆的过程,这玩意在\(\rm BZOJ\)好像会发生奇怪的错误反正窝是MLE了,所以我们记个编号就好了。好像原因是因为BZOJ不支持c++11...

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} #define ll long long void print(ll x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-8; int head[maxn],tot,n,a[maxn],sta[maxn],top,id[maxn];
struct edge{int to,nxt;}e[maxn<<1]; priority_queue<int > s[maxn]; void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
void ins(int u,int v) {add(u,v),add(v,u);} void dfs(int x,int fa) {
for(int v,i=head[x];i;i=e[i].nxt) {
if((v=e[i].to)==fa) continue;top=0;dfs(v,x);
if(s[id[v]].size()>s[id[x]].size()) swap(id[x],id[v]);
while(s[id[v]].size()) sta[++top]=max(s[id[x]].top(),s[id[v]].top()),s[id[x]].pop(),s[id[v]].pop();
while(top) s[id[x]].push(sta[top--]);
}s[id[x]].push(a[x]);
} int main() {
read(n);for(int i=1;i<=n;i++) read(a[i]),id[i]=i;
for(int i=2,x;i<=n;i++) read(x),ins(i,x);
dfs(1,0);ll ans=0;while(s[id[1]].size()) ans+=(ll)s[id[1]].top(),s[id[1]].pop();
write(ans);
return 0;
}
上一篇:asp.net中父子页面通过gridview中的按钮事件进行回传值的问题


下一篇:GridView中的更新按钮不能触发RowUpdating事件