Mashmokh and ACM CodeForces - 414D (贪心)

Posted uid001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
", min(ans, k));
}

 

以上是关于Mashmokh and ACM CodeForces - 414D (贪心)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 414B Mashmokh and ACM

Mashmokh and ACM CodeForces - 414D (贪心)

CodeForces - 415B Mashmokh and Tokens

Round #240 B. Mashmokh and Tokens(Div.2)

Mashmokh's Designed Problem 01生成树

@codeforces - 414E@ Mashmokh's Designed Problem