zoukankan      html  css  js  c++  java
  • 【洛谷P5290】【LOJ3052】春节十二响【堆】

    题目大意:

    题目链接:
    洛谷:https://www.luogu.org/problemnew/show/P5290
    LOJ:https://loj.ac/problem/3052
    将一棵树的每一个节点划分进一个集合,要求任意集合内的任意两点不可以是祖先 — 后代关系,每一个集合的费用为该集合内点的最大权值。求最小费用和。


    思路:

    我们假设一个节点有两个子节点,并且以该节点为根的子树全部只有一个子节点(该节点除外)
    在这里插入图片描述
    设黄色节点的最大值为maxmax且在以xx为根的子树内,那么xx显然是要与以yy为根的子树内的最大权值的节点合并的,这样显然可以减少接下来合并的费用。
    那么我们将xxyy合并时,我们对于每一个子树合并一个堆,每次将堆顶元素取出并合并为权值更大的那个。这样我们就维护好了两个子树的费用。
    假设rootroot有多个子节点,那么我们每次合并两个节点,并赋值到rootroot中,所有子节点的集合合并完之后再将rootroot的权值加入堆中。
    但是这样的时间复杂度很容易被卡,所以我们要用启发式合并,每次把大小相对小的往大小相对大的合并,这样每一个节点最多被合并lognlog n次,时间复杂度O(nlogn)O(nlog n)


    代码:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N=200010;
    int n,tot,a[N],head[N],p[N];
    priority_queue<int> q[N];
    ll ans;
    
    struct edge
    {
    	int next,to;
    }e[N];
    
    void add(int from,int to)
    {
    	e[++tot].to=to;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    void merge(int &x,int &y)
    {
    	if (q[x].size()<q[y].size()) swap(x,y);
    	while (q[y].size())
    	{
    		q[0].push(max(q[x].top(),q[y].top()));
    		q[x].pop(); q[y].pop();
    	}
    	for (;q[0].size();q[0].pop()) q[x].push(q[0].top());
    }
    
    void dfs(int x)
    {
    	p[x]=x;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		dfs(e[i].to);
    		merge(p[x],p[e[i].to]);
    	}
    	q[p[x]].push(a[x]);
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	for (int i=2,x;i<=n;i++)
    	{
    		scanf("%d",&x);
    		add(x,i);
    	}
    	dfs(1);
    	for (;q[p[1]].size();q[p[1]].pop())
    		ans+=q[p[1]].top();
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Jquery-EasyUI学习2~
    IIS——发布网站
    一致性哈希算法
    利用ZTree链接数据库实现 [权限管理]
    Form表单提交的简要方式
    Redis学习之5种数据类型操作、实现原理及应用场景
    redis对比其余数据库
    ZooKeeper概述(转)
    Zookeeper-Zookeeper可以干什么
    Java内存分配及变量存储位置实例讲解
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998086.html
Copyright © 2011-2022 走看看