codeforces 414D Mashmokh and Water Tanks

codeforces 414D Mashmokh and Water Tanks

题意

题解

\(a_i\):第 \(i\) 层的结点个数。
\(b_i\):第 \(i\) 层初始有水的结点个数。
如果不允许关闭水塔,最后的答案就是 \(max\{a_i\}\)
现在允许关闭部分水塔,我们可以把一些连续层数的水汇聚到同一层。假设我们汇聚 \([l, r]\) 范围的水,总花费是 \(\Sigma_{i=l}^r\{b_i*(r-i)\}\)
双指针实现即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(x) (int)x.size()
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N=101010;
int n,k,p,ma;
int a[N];
vi g[N];

void dfs(int u,int fa,int d) {
	++a[d];
	ma=max(d, ma);
	rep(i,0,sz(g[u])) {
		int v=g[u][i];
		if(v==fa) continue;
		dfs(v, u, d+1);
	}
}

int main() {
	while(~scanf("%d%d%d",&n,&k,&p)) {
		///init
		rep(i,0,n+1) g[i].clear();
		ma=0;
		memset(a,0,sizeof(a));
		///read
		rep(i,1,n) {
			int u,v;scanf("%d%d",&u,&v);
			g[u].pb(v);
			g[v].pb(u); 
		}
		///solve
		dfs(1,1,0);
		ll c=0, v=0, f=a[1], ans=0;
		for(int l=1, r=1;r<=ma;++r) {
			c+=v;
			v+=a[r];
			while(v>k) {
				ll sub=min(f, v-k);
				c-=sub*(r-l);
				v-=sub;
				f-=sub;
				if(f==0) {
					++l;
					f=a[l];
				}
			}
			while(c>p) {
				ll sub=min(f, (c-p)/(r-l)+((c-p)%(r-l)>0));
				c-=sub*(r-l);
				v-=sub;
				f-=sub;
				if(f==0) {
					++l;
					f=a[l];
				}
			}
			ans=max(ans, v);
		}
		printf("%lld\n",ans);
	}
	return 0;
}
/*
10 2 1
1 2
1 3
3 4
3 5
2 6
6 8
6 7
9 8
8 10

5 1000 1000
1 2
1 3
3 4
3 5
*/
posted @ 2018-03-23 11:35  yuanyuan-97  阅读(149)  评论(0编辑  收藏  举报