题目传送门

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序+线段树的更多相关文章

  1. 【bzoj3252】攻略 贪心+DFS序+线段树

    题目描述 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某 ...

  2. [Bzoj3252]攻略(dfs序+线段树)

    Description 题目链接 Solution 可以想到,每次肯定是拿最大价值为最优 考虑改变树上一个点的值,只会影响它的子树,也就是dfs序上的一个区间, 于是可以以dfs序建线段树,这样就变成 ...

  3. BZOJ 3252题解(贪心+dfs序+线段树)

    题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...

  4. BZOJ3252 攻略(贪心+dfs序+线段树)

    考虑贪心,每次选价值最大的链.选完之后对于链上点dfs序暴力修改子树.因为每个点最多被选一次,复杂度非常正确. #include<iostream> #include<cstdio& ...

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

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  6. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  7. 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 ...

  8. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  9. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

随机推荐

  1. React-Native 之 GD (六)无数据情况处理

    1.还是网络问题,在网络出现问题或者无法加载数据的时候,一般我们会展示空白页,在空白页中提示 无数据 之类的提示,比较好的还会使用 指示器 的方式告诉用户网络出现问题等等. 这边我们做以下处理,当无数 ...

  2. Linux中的NetworkManager网络管理

    转载关于 NM_CONTROLLED和Network Manager Redhat在RHEL 6(Redhat Enterprise Linux),上搞了一个 Network manger 服务(同样 ...

  3. ctrl+r 调用bash曾经的历史命令

    在bash界面 按ctrl+r 可以调出, bash中曾经的历史命令, 光标会停留在 第一次被匹配的字符上, (即使后面你再输入被匹配的字符, 光标也不移动) 然后, 根据你的需要 来进行任何一次的操 ...

  4. mycat 配置简介

    最近在看 mycat ,官网: http://www.mycat.io/  上面就有 PDF 的教程下载.但是对于我这个初学者来讲,搭建环境的时候还是有点晕,下面从一个简单的例子来讲解相关配置.我用的 ...

  5. ubuntu 安装 rocketmq

    1.安装 rocketmq首先要有java以及maven环境,这里略过,可参考 https://www.cnblogs.com/xiaobaoTribe/p/11315011.html  安装JDK ...

  6. js高级写法

    名称 一般写法 优化 取整(不四舍五入) parseInt(a,10); //Before Math.floor(a); //Before a>>0; //Before ~~a; //Af ...

  7. 测开之路一百一十二:bootstrap按钮

    bootstrap按钮 引入bootstrap和jquery 普通按钮和bootstrap风格按钮 调整大小 块级按钮 禁用按钮 disabled 按钮分组 分页按钮

  8. python爬虫常用数据整理函数

    text()                       获取xpath中的值....../h1/text() extract()[0]              Selector的方法用于提取内容为 ...

  9. oracle--表空间处理

    CREATE TABLESPACE命令详解(转) 表空间理解 https://www.cnblogs.com/kerrycode/p/3418694.html 常用操作 https://www.cnb ...

  10. 前端 CSS 盒子模型

    盒模型的概念 在CSS中,"box model"这一术语是用来设计和布局时使用,然后在网页中基本上都会显示一些方方正正的盒子.我们称为这种盒子叫盒模型. 盒模型有两种:标准模型和I ...