首页 > 其他分享 >P3780 [SDOI2017] 苹果树 题解

P3780 [SDOI2017] 苹果树 题解

时间:2023-08-17 16:36:46浏览次数:36  
标签:tmp le val int 题解 back P3780 苹果 SDOI2017

Description

P3780 [SDOI2017] 苹果树

给定一棵 \(n\) 个点的树,每个点有若干个价值相同的苹果,儿子能摘至少一个仅当父亲被摘至少一个。

给定 \(k\),设 \(h\) 为你摘的苹果的最大深度,你做多能摘 \(k+h\) 个,求最大价值。

对于所有数据,\(1\le n\le 5\times 10^4\),\(1\le k\le 5\times 10^5\),\(1\le nk\le 2.5\times 10^7\)。

Solution

深度的条件可以转化为免费选一条链,得到链每个点上的一个苹果。

考虑枚举这条链,链将苹果分为三类:链上每个点的一个免费苹果,链左边的与链上剩余付费苹果,链右边的付费苹果。第一类可以简单处理出每个点到根路径上的价值和,对于第二三类考虑 DP 后对每条链合并。

设 \(f_{i,k,j}\) 为考虑根到节点 \(i\) 的链及其左边的,\(i\) 的前 \(k\) 棵子树里的,除去链上每个点免费的苹果,摘了 \(j\) 个最大的价值。转移分两种:

  • 父亲将链及左边转移给儿子:枚举 \(u\) 的每个儿子 \(v\),设 \(v\) 为 \(u\) 从左到右的第 \(t\) 个儿子。先将 \(f_{u,t-1}\) 的值拷贝给 \(f_{v,0}\),然后加入 \(v\) 的苹果,对 \(f_{v,0}\) 跑多重背包(可以不选)。由于要减去一个免费的,所以只能加入 \(a_{v}-1\) 个苹果。转移后递归 \(v\) 的子树。
  • 儿子将子树转移给父亲:沿用上文的 \(u,v,t\)。递归 \(v\) 的子树后,更新 \(f_{u,t}\)。由于 \(v\) 处不一定选了苹果,所以要强制加入一个 \(v\) 苹果来更新:\(\displaystyle f_{u,t,j}=\max\{f_{u,t-1,j},f_{v,\operatorname{sonsize}(v),j-1}+val_{v}\}\)。

实现的时候不用记第二维。多重背包要用单调队列优化,如果您不会可以先去学习 P1776 宝物筛选

同理,设 \(g_{i,k,j}\) 为考虑根到节点 \(i\) 的链右边的(不包括这条链),\(i\) 的 \(k\) 棵子树里的的苹果,摘了 \(j\) 个最大的价值。转移类似:

  • 父亲将链右边转移给儿子:枚举 \(u\) 的每个儿子 \(v\),设 \(v\) 为 \(u\) 从右到左的第 \(t\) 个儿子。将 \(g_{u,t-1}\) 的值拷贝给 \(g_{v,0}\),然后递归 \(v\) 的子树。
  • 儿子将子树转移给父亲:沿用 \(u,v,t\)。递归 \(v\) 的子树后,复制一份 \(tmp=g_{v,\operatorname{sonsize}(v)}\),用 \(v\) 节点上的苹果对 \(tmp\) 跑多重背包(不能不选),然后来更新 \(g_{u,t}\) 即可:\(\displaystyle g_{u,t,j}=\max\{g_{u,t-1,j},tmp_{j}\}\)。

为了方便,实现时 \(a_{v}\) 次不能不选的背包可以转化成 \(a_{v}-1\) 可以可以不选的背包与最后一次必选。

时间复杂度 \(\mathcal{O}(nk)\)。

Code

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
using namespace std;
namespace Milkcat {
	typedef long long LL;
	typedef pair<LL, LL> pii;
    typedef vector<LL> poly;
	const int N = 2e4 + 5;
	int n, k, u, v, ans, a[N], val[N], sum[N], siz[N];
	vector<int> G[N], f[N], g[N];
	void update(vector<int>& f, int c, int v) {
		vector<int> g(f.size()); deque<int> q;
		for (int i = 0; i <= k; i ++) {
			while (!q.empty() && i - q.front() > c) q.pop_front();
			while (!q.empty() && f[i] - v * i > f[q.back()] - v * q.back()) q.pop_back();
			q.push_back(i), g[i] = f[q.front()] + v * (i - q.front());
		}
		g.swap(f);
	}
	void dfs1(int u, int fa) {
		update(f[u], a[u] - 1, val[u]);
		sum[u] = sum[fa] + val[u], siz[u] = 1;
		for (int v : G[u]) {
			if (v == fa) continue;
			f[v] = f[u], dfs1(v, u), siz[u] += siz[v];
			for (int i = 1; i <= k; i ++)
				f[u][i] = max(f[u][i], f[v][i - 1] + val[v]);
		}
	}
	void dfs2(int u, int fa) {
		reverse(G[u].begin(), G[u].end());
		for (int v : G[u]) {
			if (v == fa) continue;
			g[v] = g[u], dfs2(v, u);
			vector<int> tmp(g[v]);
			update(tmp, a[v] - 1, val[v]);
			for (int i = 1; i <= k; i ++)
				g[u][i] = max(g[u][i], tmp[i - 1] + val[v]);
		}
	}
	int main() {
		cin >> n >> k;
		for (int i = 1; i <= n; i ++) {
			cin >> u >> a[i] >> val[i];
			if (u) G[u].pb(i), G[i].pb(u); 
		}
		f[1].resize(k + 2), g[1].resize(k + 2);
		dfs1(1, 0), dfs2(1, 0);
		for (int i = 1; i <= n; i ++) {
			if (siz[i] > 1) continue;
			for (int j = 0; j <= k; j ++)
				ans = max(ans, f[i][j] + g[i][k - j] + sum[i]);
		}
		cout << ans << '\n';
		return 0;
	}
	void clear() {
		f[1].clear(), g[1].clear(), ans = 0;
		for (int i = 1; i <= n; i ++) G[i].clear();
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
    int T = 1; cin >> T;
    while (T --) Milkcat::main(), Milkcat::clear();
    return 0;
}

标签:tmp,le,val,int,题解,back,P3780,苹果,SDOI2017
From: https://www.cnblogs.com/Milkcatqwq/p/17638009.html

相关文章

  • P4183 [USACO18JAN] Cow at Large P 题解
    题意分析我们首先想到,枚举贝茜在\(x\)点,枚举度数大于\(2\)的点为\(y\)。设\(x\)的度数为\(a\),\(y\)的度数为\(b\)。我们首先发现每个\(x\)点都有一个初始的贡献为\(a\)条通往叶子的路径。如果点\(y\)到最近的叶子节点的距离大于到\(x\)的点的距离(农夫不能在......
  • 安防监控视频汇聚平台EasyCVR视频平台调用iframe地址无法播放的问题解决方案
    安防监控视频汇聚平台EasyCVR基于云边端一体化架构,具有强大的数据接入、处理及分发能力,可提供视频监控直播、云端录像、视频云存储、视频集中存储、视频存储磁盘阵列、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、AI算法中台智能分析无缝对接等功能。为了便于用户......
  • 安防监控视频汇聚平台EasyCVR视频平台调用iframe地址无法播放的问题解决方案
    安防监控视频汇聚平台EasyCVR基于云边端一体化架构,具有强大的数据接入、处理及分发能力,可提供视频监控直播、云端录像、视频云存储、视频集中存储、视频存储磁盘阵列、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、AI算法中台智能分析无缝对接等功能。为了便于用户二......
  • vue项目在360浏览器兼容模式下SCRIPT1002: 语法错误以及“fetch”未定义问题解决
    使用360浏览器的兼容模式,vue项目页面空白,打开控制台,发现如下报错:SCRIPT1002:语法错误 解决方法如下:1、安装依赖npminstall--savecore-jsregenerator-runtime2、在main.js引入import'core-js/stable';import'regenerator-runtime/runtime';3、在babel.confi......
  • CF1545B题解
    CF1545B题解题目描述你有一个长为\(n\)的棋盘,这个棋盘上有一些棋子,你可以进行如下操作:如果第\(i+2\)个位置是空的,且第\(i+1\)个位置非空,则可以将第\(i\)个位置的棋子挪到第\(i+2\)个位置(\(i+2\leqn\)).如果第\(i-2\)个位置是空的,且第\(i-1......
  • arc136,arc137,arc138题解
    ARC136A-EAA↔BB贪心。可以把BB换成A,可以把BA换成AB。BTripleShift直观上觉得只要数集相同,那么就是可以变换的。大概方法就是每次找到正确的数把它挪到数列的端点,这样显然是可行的。但是在相反的三个上出现了问题,原因在于只剩最后两个数时方向可能是反着的。分析......
  • arc133,arc134,arc135题解
    ARC133A-EAErasebyValue扣掉一个数当且仅当这个数后面有更小的数。特判单增即可。BDividingSubsequence相对比较有启发性。发现有倍数关系的数对只有\(O(n\logn)\)对,于是可以把对应下标攒成一堆二元组,于是一个合法的取数方案就变成了两个维度分别严格上升的元素集合......
  • arc130,arc131,arc132题解
    ARC130A-DARemoveOneCharacter对每个连续块分别处理即可。BColorfulLines非常经典的题目,对于每一行每一列记录最后出现的颜色并计算贡献即可。CDigitSumMinimization有点细节。枚举最后两个数,显然加起来超过十是很好的;然后前面的数应该尽量凑九,然后要注意尽量不选......
  • FJOI2018 领导集团问题 题解
    先考虑暴力dp。设\(f_{u,x}\)表示在子树\(u\)中选出的节点集合的\(w\)最小值为\(x\)的情况下,最大的节点集合的大小。有两种转移(选不选\(u\)):\(f_{u,x}\gets\sum\limits_{v\in\text{substree}_u}f_{v,\gex}\)\(f_{u,w_u}\gets\sum\limits_{v\in\text{substree}_u}......
  • [CF1730D] Prefixes and Suffixes 题解
    首先发现后缀和前缀比较不好看,所以翻转第二个字符串,记为\(T'\)。这样就变成了操作两个字符串的前缀。观察发现,操作\(k\)等价于交换\(S[1\simk]\)和\(T'[1\simk]\),然后翻转\(S[1\simk]\)和\(T'[1\simk]\)。结论1:同一个下标上的字符对恒定。因为我们所有的操作都......