[HYSBZ - 3252] 攻略

问题描述

题目简述:树版[k取方格数]

众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏。今天他得到了一款新游戏《XX

半岛》,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景。所有场景和选择支构成树状

结构:开始游戏时在根节点(共通线),叶子节点为结局。每个场景有一个价值,现在桂马开启攻略之神模式,同

时攻略k次该游戏,问他观赏到的场景的价值和最大是多少(同一场景观看多次是不能重复得到价值的)

“为什么你还没玩就知道每个场景的价值呢?”

“我已经看到结局了。”

输入格式

第一行两个正整数n,k

第二行n个正整数,表示每个场景的价值

以下n-1行,每行2个整数a,b,表示a场景有个选择支通向b场景(即a是b的父亲)

保证场景1为根节点

n<=200000,1<=场景价值<=2^31-1

输出格式

输出一个整数表示答案

样例输入

5 2
4 3 2 1 1
1 2
1 5
2 3
2 4

样例输出

10

解析

显然,第一次一定是走树上权值最大的一条路径。在此后的\(k-1\)次中,每次都会走出去已经走过的路径以外最长的。 接下来的路径,并不一定是从根节点出发的,可以从已经走过的点的子节点出发,也一样可以满足条件。那么,设\(f[i]\)表示以\(i\)为根节点的子树上的最长路径长度,每次从堆中取出最长的一条路径后,把这条路径上每一个点的所有子节点的\(f[i]\)放入堆中。\(f[i]\)可以由动态规划处理,并在同时用前驱数组记录路径经过的点。

P.S. 代码中的堆是用左偏树实现的。

代码

#include <iostream>
#include <cstdio>
#include <queue>
#define int long long
#define N 200002
using namespace std;
int head[N],ver[N*2],nxt[N*2],val[N],l;
int n,k,i,id,pre[N],f[N],pnt[N],son[N][2],fa[N],dis[N];
void insert(int x,int y)
{
    l++;
    ver[l]=y;
    nxt[l]=head[x];
    head[x]=l;
}
void dp(int x,int fa)
{
    pre[x]=fa;
    for(int i=head[x];i;i=nxt[i]){
        int y=ver[i];
        if(y!=fa){
            dp(y,x);
            if(f[y]>f[x]) f[x]=f[y],pnt[x]=y;
        }
    }
    f[x]+=val[x];
}
int merge(int x,int y)
{
    if(x==0) return y;
    if(y==0) return x;
    if(f[x]<f[y]) swap(x,y);
    son[x][1]=merge(son[x][1],y);
    if(dis[son[x][0]]<dis[son[x][1]]) swap(son[x][0],son[x][1]);
    dis[x]=dis[son[x][1]]+1;
    fa[x]=fa[son[x][0]]=fa[son[x][1]]=x;
    return x;
}
int find(int x)
{
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
void pop(int x)
{
    f[x]=-1;
    fa[son[x][0]]=son[x][0];
    fa[son[x][1]]=son[x][1];
    fa[x]=merge(son[x][0],son[x][1]);
}
void insert(int x)
{
    while(x){
        pop(x);
        for(int i=head[x];i;i=nxt[i]){
            int y=ver[i];
            if(y!=pre[x]&&y!=pnt[x]) merge(y,find(n+1));
        }
        x=pnt[x];
    }
}
signed main()
{
    cin>>n>>k;
    for(i=1;i<=n;i++) cin>>val[i],fa[i]=i;
    fa[n+1]=n+1;f[n+1]=-1;
    for(i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        insert(u,v);
        insert(v,u);
    }
    dp(1,0);
    int ans=f[1];
    insert(1);
    for(i=1;i<k;i++){
        int root=find(n+1);
        ans+=f[root];
        insert(root);
    }
    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/LSlzf/p/11072548.html

时间: 2024-10-16 13:59:36

[HYSBZ - 3252] 攻略的相关文章

【贪心】 BZOJ 3252:攻略

3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 261  Solved: 90[Submit][Status][Discuss] Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景.所有场景和选择支构成树状结构:开始游戏时在根节点(共通线),

BZOJ 3252 攻略 线段树

题意:链接 方法:线段树 解析: 闲的随机的题. 看完题后看着好像挺简单的. 既然每个点的权值只会传子树,并且整个图是严格的一棵树,所以应该是跟dfs序有关. 然后去看数据范围. 尼玛HINT是什么鬼. 既然这么说了那就想想怎么做吧=-= 并且因为价值都为正的,所以显然要考虑贪心,挑k条从叶节点到根的所有点权值和最大的k条. 并且每一挑完后都需要更新. 然后有一个性质,每个点至多选一次,也就是说每个点至多被删一次. 并且根节点到叶节点链上的所有点的路径上的点权和是随着深度递增的. 所以显然我们用

bzoj 3252 攻略

题目大意: 树上每个点有一个正的点权,选k条不相交的链使权值和最大 思路: 被长链剖分的标签骗进来 法1: 这道题长链剖分标签的由来,类似重链剖分把树剖成若干条链,然后贪心的选k条即可 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #inc

【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景.所有场景和选择支构成树状结构:开始游戏时在根节点(共通线)

线段树 BZOJ3252 攻略

3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 496  Solved: 211[Submit][Status][Discuss] Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景.所有场景和选择支构成树状结构:开始游戏时在根节点(共通线)

移动端点击事件全攻略,有你知道与不知道的各种坑

看标题的时候你可能会想,点击事件有什么好说的,还写一篇攻略?哈哈,如果你这么想,只能说明你too young to simple. 接触过移动端开发的同学可能都会面临点击事件的第一个问题:click事件的300ms延迟响应.不能立即响应给体验造成了很大的困扰,因此解决这个问题就成为了必然. 这个问题的解决方案就是: zepto.js的tap事件.tap事件可以理解为在移动端的click事件,而zepto.js因为几乎完全复制jQuery的api,因此常常被用在h5的开发上用来取代jquery.

Azure进阶攻略丨Azure网络通不通,PsPing&amp;PaPing告诉你答案

很多时候,为了解决一些问题,要查各种文档,很麻烦你造吗!做「伸手党」又容易被鄙视,这时候就需要用到[Azure 进阶攻略]啦!特此,我们推出关于 Azure 常用操作指南的系列文章,每篇涉及一个 Azure 使用过程中的问题,简明扼要直击重点,纯干货内容帮你快速搞定 Azure 使用难题和障碍,只需一两分钟阅读,你就可以继续愉快地翱翔云端~ 在技术人员和网络工程师的世界中,有一些众所周知的排错方式,例如: -你先 Ping 一下某某计算机,看它开着没, -我可以 Ping 通路由器,但 Ping

广州去厦门旅游攻略--(转自 #散文吧网站#)

广州去厦门旅游攻略 发布时间:2016-12-11 17:30 厦门由厦门岛.离岛鼓浪屿.内陆九龙江南岸海沧半岛.集美半岛.翔安区以及同安等组成,陆地面积1699.39Km2,海域面积300多平方公里.厦门的主体--厦门岛南北长13.7公里,东西宽12.5公里,面积约为128.14Km2.是厦门的主要岛屿,也是厦门第一大岛屿.厦门岛是厦门经济特区的发祥地,岛上有厦门的商业和政治中心.各国殖民者最初居住的地方鼓浪屿就在厦门岛西南部.今天小编带给大家的是广州去厦门旅游攻略, 希望对大家有帮助. 厦门

Linux Shell脚本攻略(1.12)

1.12 函数和参数 和其他脚本语言一样,Bash同样支持函数,并且可以传递参数. 1.12.1 函数定义和传参 #!/bin/bash function fname() #也可以用fname()代替 { echo $1,$2; #访问参数1和参数2 echo "[email protected]"; #以列表的方式一次性打印所有参数 echo "$*"; #类似于[email protected],但是参数被作为单个实体 return 0; #返回值 } fnam