【bzoj3252】攻略 贪心+DFS序+线段树
题目描述
输入
输出
样例输入
5 2
4 3 2 1 1
1 2
1 5
2 3
2 4
样例输出
10
题解
贪心+DFS序+树状数组
首先有个显而易见的贪心策略:每次选能够获得最大价值的点。
于是我们只需要设法维护这个贪心即可。
考虑到一个点被使用,影响到的只有它的子树中的节点。所以我们可以按路径长度对DFS序上每个点建立线段树,并线段树维护DFS序上的区间最大值、区间最大值位置,支持修改操作。
所以我们每次操作拿出最大值加到答案中,并对于最大值位置对应的点,在它到根节点的路径上不断向上移动,每到一个点就更新它的子树,把它们的价值减去这个点的权值。直到移动到某个已经被使用了的点停止。(因为如果一个点被使用,则它的祖先节点也一定均被使用)。
时间复杂度为$O((n+k)\log n)$。
#include <cstdio>
#include <algorithm>
#define N 200010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
int fa[N] , head[N] , to[N] , next[N] , cnt , pos[N] , ref[N] , last[N] , tot , mp[N << 2] , del[N];
ll w[N] , v[N] , mx[N << 2] , tag[N << 2];
void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x)
{
int i;
v[x] = v[fa[x]] + w[x] , pos[x] = ++tot , ref[tot] = x;
for(i = head[x] ; i ; i = next[i]) dfs(to[i]);
last[x] = tot;
}
void pushup(int x)
{
int l = x << 1 , r = x << 1 | 1;
if(mx[l] > mx[r]) mx[x] = mx[l] , mp[x] = mp[l];
else mx[x] = mx[r] , mp[x] = mp[r];
}
void pushdown(int x)
{
if(tag[x])
{
int l = x << 1 , r = x << 1 | 1;
mx[l] -= tag[x] , mx[r] -= tag[x];
tag[l] += tag[x] , tag[r] += tag[x];
tag[x] = 0;
}
}
void build(int l , int r , int x)
{
if(l == r)
{
mx[x] = v[ref[l]] , mp[x] = l;
return;
}
int mid = (l + r) >> 1;
build(lson) , build(rson);
pushup(x);
}
void update(int b , int e , ll a , int l , int r , int x)
{
if(b <= l && r <= e)
{
mx[x] -= a , tag[x] += a;
return;
}
pushdown(x);
int mid = (l + r) >> 1;
if(b <= mid) update(b , e , a , lson);
if(e > mid) update(b , e , a , rson);
pushup(x);
}
int main()
{
int n , k , i , x , y;
ll ans = 0;
scanf("%d%d" , &n , &k);
for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &w[i]);
for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , fa[y] = x , add(x , y);
dfs(1);
build(1 , n , 1);
while(k -- )
{
ans += mx[1] , x = ref[mp[1]];
while(x && !del[x]) update(pos[x] , last[x] , w[x] , 1 , n , 1) , del[x] = 1 , x = fa[x];
}
printf("%lld\n" , ans);
return 0;
}
【bzoj3252】攻略 贪心+DFS序+线段树的更多相关文章
- bzoj3252 攻略 贪心+dfs序+线段树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3252 题解 有一个非常显然的贪心思路:每次选择目前走到那儿能够获得的新权值最大的点. 证明的话 ...
- [Bzoj3252]攻略(dfs序+线段树)
Description 题目链接 Solution 可以想到,每次肯定是拿最大价值为最优 考虑改变树上一个点的值,只会影响它的子树,也就是dfs序上的一个区间, 于是可以以dfs序建线段树,这样就变成 ...
- BZOJ 3252题解(贪心+dfs序+线段树)
题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...
- BZOJ3252 攻略(贪心+dfs序+线段树)
考虑贪心,每次选价值最大的链.选完之后对于链上点dfs序暴力修改子树.因为每个点最多被选一次,复杂度非常正确. #include<iostream> #include<cstdio& ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)
A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
随机推荐
- 剑指offer18 树的子结构
另一种写法 class Solution { public: bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { bool result = f ...
- Cookie中存放数据l加密解密的算法
public class CookieUtil { /** * * @param response HttpServletResponse类型的响应 * @param cookie 要设置httpOn ...
- 01_9_Struts用ModelDriven接收参数
01_9_Struts用ModelDriven接收参数 1. 配置struts.xml文件 <package name="user" namespace="/use ...
- Java中什么是匿名对象,空参构造方法输出创建了几个匿名对象,属性声明成static
package com.swift; //使用无参构造方法自动生成对象,序号不断自增 public class Person { private static int count; //如果在定义类时 ...
- [vijos]P1642 班长的任务
背景 十八居士的毕业典礼(1) 描述 福州时代中学2009届十班同学毕业了,于是班长PRT开始筹办毕业晚会,但是由于条件有限,可能每个同学不能都去,但每个人都有一个权值,PRT希望来的同学们的权值总和 ...
- 阿里云服务器 - node启动服务的时候只有监听内网IP才可以供外网访问
阿里云服务器 - node启动服务的时候只有监听内网IP才可以供外网访问
- k8s的Pod控制器
pod的配置清单常见选项: apiVersion,kind,metadata,spec,status(只读) spec: containers: nodeSelector: nodeName: res ...
- 有关Kali的方法
Kali 找回系统登陆密码的方式:https://jingyan.baidu.com/article/47a29f24560e77c0142399e3.html
- 关于使用Java实现的简单网络爬虫Demo
什么是网络爬虫? 网络爬虫又叫蜘蛛,网络蜘蛛是通过网页的链接地址来寻找网页,从网站某一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其它链接地址,然后通过这些链接地址寻找下一个网页,这样一直 ...
- redis列表,字典,管道,vue安装,创建项目
redis mysql,redis,mogondb 1.mysql,oracle:关系型数据库,有表概念 2.redis,mongodb/nosql:非关系型数据库 没有表概念 mongodb存储在硬 ...