Mashmokh and ACM CodeForces - 414D (贪心)

大意: 给定n结点树, 有k桶水, p块钱, 初始可以任选不超过k个点(不能选根结点), 在每个点放一桶水, 然后开始游戏. 游戏每一轮开始时, 可以任选若干个节点关闭, 花费为关闭结点储存水的数量和, 然后未关闭的非根结点上的水会流入父结点, 然后再开始新的一轮. 当所有非根结点无水后游戏结束, 假设第$i$轮流入根节点的水为$w_i$, 游戏共进行了$l$轮, 求$max(w_1,w_2,...,w_l)$

可以发现最优时一定是一段深度相邻的水, 所以双指针维护一段连续的区间就行了.

考虑每个区间的花费怎样计算, 一个显然的贪心策略是: 每次都关闭深度最低的点, 直到这段区间的水深度相同为止.

假设现在维护的区间为$[l,r]$, 若添加一个点$r+1$, 若$dep[r+1]=dep[r]$则花费不增加, 否则需要多等待它一回合, 花费增加$r-l+1$. 若删除左端点$l$, 花费减少量即为左端点的关闭次数$dep[r]-dep[l]$

双指针具体实现的话, 因为有0贡献点的存在,  按我以前的写法会少更新ans, 解决方法是在移动右端点前更新一下ans

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#define pb push_back
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
typedef long long ll;

const int N = 1e5+10, INF = 0x3f3f3f3f;
int n, k, p, cnt;
vector<int> g[N];
int dep[N];

void dfs(int x, int fa, int d) {
	if (x!=1) dep[++cnt] = d;
	for (int y:g[x]) if (y!=fa) dfs(y,x,d+1);
}

int main() {
	scanf("%d%d%d", &n, &k, &p);
	REP(i,2,n) {
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].pb(v),g[v].pb(u);
	}
	dfs(1,0,0);
	sort(dep+1,dep+1+cnt);
	int now = 1, w = 0, ans = 0;
	REP(i,1,cnt) {
		while (w<=p&&now<=cnt) {
			ans = max(ans, now-i);
			if (dep[now]!=dep[now-1]) w += now-i;
			++now;
		}
		if (w<=p) ans = max(ans, now-i);
		w -= dep[now-1]-dep[i];
	}
	printf("%d\n", min(ans, k));
}

原文地址:https://www.cnblogs.com/uid001/p/10425757.html

时间: 2024-12-28 13:00:49

Mashmokh and ACM CodeForces - 414D (贪心)的相关文章

【codeforces 415D】Mashmokh and ACM(普通dp)

[codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=2000),问满足[数列长度是k && 数列中每一个元素arr[i]在1~n之间 && 数列中元素可以重复]的数列有多少个?结果对10^9+7取余 解题思路:dp[i][j]表示长度是j,最后一位是i的种数 if(kk%i==0) dp[kk][j+1]+=dp[i][j] 1 #i

Codeforces 437D 贪心+并查集

这个题目让我想起了上次在湘潭赛的那道跪死了的题.也是最值问题,这个也是,有n个动物园 每个都有权值 然后被m条路径相连接,保证图是连通的,然后求所有的p[i][j]之和.i,j为任意两个zoo,pij就为i到j路上遇到的包括i j在内的最小权值的zoo 然后我就焦头烂额了一下,这个明显就是看某个最小值为最后的结果发挥了多少次作用,但这个是图,要知道某个节点到底给多少条路径贡献出了最小值,还真是有点没头绪(在已知的复杂度一看 最多只能用nlogn的),最后是看了解答才知道的 用并查集来解决某个最小

Codeforces 414B Mashmokh and ACM(DP)

Mashmokh's boss, Bimokh, didn't like Mashmokh. So he fired him. Mashmokh decided to go to university and participate in ACM instead of finding a new job. He wants to become a member of Bamokh's team. In order to join he was given some programming tas

Codeforces Round #240 (Div. 1)---B.Mashmokh and ACM(dp)

Mashmokh's boss, Bimokh, didn't like Mashmokh. So he fired him. Mashmokh decided to go to university and participate in ACM instead of finding a new job. He wants to become a member of Bamokh's team. In order to join he was given some programming tas

codeforces 414B B. Mashmokh and ACM(dp)

题目链接: codeforces 414B 题目大意: 定义一个序列,前一项能够整除后一项,给定这个序列中数的取值范围和序列的长度,问有多少种构造方法. 题目分析: 我们定义状态dp[i][j]为前i项已经确定且第i项为j的方案数. 转移方程 dp[i][j]=∑k|jdp[i?1][k] 复杂度O(n?k) AC代码: #include <iostream> #include <cstring> #include <algorithm> #include <cs

CodeForces 415D Mashmokh and ACM

$dp$. 记$dp[i][j]$表示已经放了$i$个数字,并且第$i$个数字放了$j$的方案数.那么$dp[i][j] = \sum\limits_{k|j}^{}  {dp[i - 1][k]}$ #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorit

CodeForces 414B - Mashmokh and ACM

给你长度为 l 的整数数列b1, b2, ..., bl(1 ≤ b1 ≤ b2 ≤ ... ≤ bl ≤ n) 如果这个数列被称为好的,那么每个元素都可以整除下一个元素 给你n和k,去找到长度为k的好数列的个数 dp[任意i][1] = 1: dp[i的倍数][长度k] = dp[i][长度k-1] + 1; 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int MOD = 100

codeforces D.Mashmokh and ACM

题意:给你n和k,然后找出b1, b2, ..., bl(1 ≤ b1 ≤ b2 ≤ ... ≤ bl ≤ n),并且对所有的bi+1%bi==0,问有多少这样的序列? 思路:dp[i][j] 表示长度为i,以j为结尾有多少.dp[i][j]+=dp[i-1][s],j%s==0; 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebo