BZOJ3252: 攻略 可并堆

网上有很多人说用dfs序+线段树做...其实stl的堆可以...可并堆可以...很多奇奇怪怪的东西都能做...

可并堆比较好想...也比较好写... 

分析:

首先,这是一个网络流做不了的题...数据太大...

其次...我们可以这样考虑一下,这个点的子树中,将这个点的权值仅更新给最大的那个就能满足

之后,在每一个叶子节点上,建立一个大根堆,dfs一遍,将子节点的堆合并,之后找到根节点,将根节点的权值加上当前位置的价值

最后,根节点中前k大的权值和即为答案...

附上代码,精简可行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <cstdio>
#include <algorithm>
#include <queue>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
using namespace std;
#define N 200005
#define ll long long
struct node
{
    int ls,rs,dis;
    ll x;
}mp[N<<1];
struct no
{
    int to,next;
}e[N<<1];
int head[N],cnt,fa[N],a[N],n,K;
void add(int x,int y)
{
    e[cnt].to=y;
    e[cnt].next=head[x];
    head[x]=cnt++;
    return ;
}
int merge(int x,int y)
{
    if(!x)return y;
    if(!y)return x;
    if(mp[x].x<mp[y].x)swap(x,y);
    mp[x].rs=merge(mp[x].rs,y);
    if(mp[mp[x].rs].dis>mp[mp[x].ls].dis)swap(mp[x].ls,mp[x].rs);
    mp[x].dis=mp[mp[x].rs].dis+1;
    return x;
}
void dfs(int x,int from)
{
    for(int i=head[x];i!=-1;i=e[i].next)
    {
        int to1=e[i].to;
        if(to1!=from)
        {
            dfs(to1,x);
            fa[x]=merge(fa[to1],fa[x]);
        }
    }
    mp[fa[x]].x+=a[x];
}
int in1[N];
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&K);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        in1[x]++,in1[y]++;
        add(x,y);
        add(y,x);
    }
    int rot=1,num=0;
    for(int i=1;i<=n;i++)
    {
        if(in1[1]==1&&in1[i]!=1)
        {
            rot=i;
        }else
        {
            num++;
            fa[i]=i;
        }
    }
    K=min(num,K);
    dfs(rot,0);
    ll ans=0;
    while(K--)
    {
        ans+=mp[fa[rot]].x;
        mp[fa[rot]].x=0;
        fa[rot]=merge(mp[fa[rot]].ls,mp[fa[rot]].rs);
    }
    printf("%lld\n",ans);
    return 0;
}

  

posted @   Winniechen  阅读(383)  评论(2编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示