zoukankan      html  css  js  c++  java
  • [启发式合并][堆]luogu P5290 [十二省联考2019]春节十二响

    题面

    https://www.luogu.com.cn/problem/P5290

    分析

    容易发现一个子树内部的选择不会影响他的兄弟子树,考虑用堆来记录当前子树的若干内存段

    显然,如果跨子树便可以选择一个与当前子树的某内存段结合。而且因为取max,所以选最大的两个结合最优

    合并堆的时候启发式合并即可

    代码

    #include <iostream>
    #include <cstdio>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int N=2e5+10;
    struct Graph {
        int v,nx;
    }g[N];
    int cnt,list[N],bel[N],a[N],acnt;
    int n,m[N];
    ll ans;
    priority_queue<int> q[N];
    
    void Add(int u,int v) {g[++cnt]=(Graph){v,list[u]};list[u]=cnt;}
    
    void Merge(int &x,int &y) {
        if (q[x].size()<q[y].size()) swap(x,y);acnt=0;
        while (!q[y].empty()) a[++acnt]=max(q[x].top(),q[y].top()),q[x].pop(),q[y].pop();
        for (int i=1;i<=acnt;i++) q[x].push(a[i]);
    }
    
    void DFS(int u) {
        for (int i=list[u];i;i=g[i].nx) DFS(g[i].v),Merge(bel[u],bel[g[i].v]);
        q[bel[u]].push(m[u]);
    }
    
    int main() {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&m[i]),bel[i]=i;
        for (int i=2,u;i<=n;i++) scanf("%d",&u),Add(u,i);
        DFS(1);
        while (!q[bel[1]].empty()) ans+=q[bel[1]].top(),q[bel[1]].pop();
        printf("%lld
    ",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    外观模式
    享元模式
    c#中的抽象类和接口
    装饰者模式
    组合模式
    适配器模式
    springboot 源码篇002## web层自动装配部分源码
    springboot 源码篇002## 自动装配原理
    springboot 源码篇 01
    shell 脚本基础 第二篇
  • 原文地址:https://www.cnblogs.com/mastervan/p/14578146.html
Copyright © 2011-2022 走看看