bzoj3252 攻略 贪心+dfs序+线段树
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=3252
题解
有一个非常显然的贪心思路:每次选择目前走到那儿能够获得的新权值最大的点。
证明的话,因为走过的点不再计入贡献,所以不这样走不可能有更优的。
考虑怎么维护每个点能够获得的新点权的最大值。
因为每个点只能做一次贡献,所以走过去以后对整个子树的作用都消失了,可以使用线段树区间修改。
还是因为每个点只能做一次贡献,所以每一次修改可以暴力跳父节点,直到跳到已经做过贡献的点为止。
时间复杂度 \(O((n+m)\log n)\)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 200000 + 7;
#define lc o << 1
#define rc o << 1 | 1
int n, k, dfc;
int a[N], f[N], dfn[N], pre[N], siz[N], vis[N];
ll dis[N];
struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }
struct Node { ll add, max; int pos; } t[N << 2];
inline void pushup(int o) {
t[o].max = 0;
if (smax(t[o].max, t[lc].max)) t[o].pos = t[lc].pos;
if (smax(t[o].max, t[rc].max)) t[o].pos = t[rc].pos;
t[o].max += t[o].add;
// dbg("o = %d, t[o].max = %lld, t[o].pos = %d\n", o, t[o].max, t[o].pos);
}
inline void build(int o, int L, int R) {
if (L == R) return t[o].max = dis[pre[L]], t[o].pos = pre[L], (void)0;
int M = (L + R) >> 1;
build(lc, L, M), build(rc, M + 1, R);
pushup(o);
}
inline void qadd(int o, int L, int R, int l, int r, int k) {
if (l <= L && R <= r) return t[o].max += k, t[o].add += k, (void)0;
int M = (L + R) >> 1;
if (l <= M) qadd(lc, L, M, l, r, k);
if (r > M) qadd(rc, M + 1, R, l, r, k);
pushup(o);
}
inline void dfs(int x, int fa = 0) {
dfn[x] = ++dfc, pre[dfc] = x, siz[x] = 1, dis[x] = dis[fa] + a[x], f[x] = fa;
for fec(i, x, y) if (y != fa) dfs(y, x), siz[x] += siz[y];
}
inline void work() {
dfs(1), build(1, 1, n);
ll ans = 0;
while (k--) {
int p = t[1].pos;
ans += t[1].max;
// dbg("p = %d, val = %lld\n", p, t[1].max + t[1].add);
while (p && !vis[p]) qadd(1, 1, n, dfn[p], dfn[p] + siz[p] - 1, -a[p]), vis[p] = 1, p = f[p];
// dbg("end: p = %d\n", p);
}
printf("%lld\n", ans);
}
inline void init() {
read(n), read(k);
for (int i = 1; i <= n; ++i) read(a[i]);
int x, y;
for (int i = 1; i < n; ++i) read(x), read(y), adde(x, y);
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
bzoj3252 攻略 贪心+dfs序+线段树的更多相关文章
- 【bzoj3252】攻略 贪心+DFS序+线段树
题目描述 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某 ...
- [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序+线段树了.而对于第二个操作,考虑再维护一 ...
随机推荐
- React-Native 之 GD (六)无数据情况处理
1.还是网络问题,在网络出现问题或者无法加载数据的时候,一般我们会展示空白页,在空白页中提示 无数据 之类的提示,比较好的还会使用 指示器 的方式告诉用户网络出现问题等等. 这边我们做以下处理,当无数 ...
- Linux中的NetworkManager网络管理
转载关于 NM_CONTROLLED和Network Manager Redhat在RHEL 6(Redhat Enterprise Linux),上搞了一个 Network manger 服务(同样 ...
- ctrl+r 调用bash曾经的历史命令
在bash界面 按ctrl+r 可以调出, bash中曾经的历史命令, 光标会停留在 第一次被匹配的字符上, (即使后面你再输入被匹配的字符, 光标也不移动) 然后, 根据你的需要 来进行任何一次的操 ...
- mycat 配置简介
最近在看 mycat ,官网: http://www.mycat.io/ 上面就有 PDF 的教程下载.但是对于我这个初学者来讲,搭建环境的时候还是有点晕,下面从一个简单的例子来讲解相关配置.我用的 ...
- ubuntu 安装 rocketmq
1.安装 rocketmq首先要有java以及maven环境,这里略过,可参考 https://www.cnblogs.com/xiaobaoTribe/p/11315011.html 安装JDK ...
- js高级写法
名称 一般写法 优化 取整(不四舍五入) parseInt(a,10); //Before Math.floor(a); //Before a>>0; //Before ~~a; //Af ...
- 测开之路一百一十二:bootstrap按钮
bootstrap按钮 引入bootstrap和jquery 普通按钮和bootstrap风格按钮 调整大小 块级按钮 禁用按钮 disabled 按钮分组 分页按钮
- python爬虫常用数据整理函数
text() 获取xpath中的值....../h1/text() extract()[0] Selector的方法用于提取内容为 ...
- oracle--表空间处理
CREATE TABLESPACE命令详解(转) 表空间理解 https://www.cnblogs.com/kerrycode/p/3418694.html 常用操作 https://www.cnb ...
- 前端 CSS 盒子模型
盒模型的概念 在CSS中,"box model"这一术语是用来设计和布局时使用,然后在网页中基本上都会显示一些方方正正的盒子.我们称为这种盒子叫盒模型. 盒模型有两种:标准模型和I ...