CF ECR 126 C. Water the Trees(二分答案)

传送门
自己想了一个结论,结果假了

求极值,而且答案有单调性,复杂度允许,应该想到要二分答案的。

答案只可能是树的最大高度\(Max \_ H\)或者\(Max \_ H+1\)
因为使所有树高度相同为\(H\)的最优操作最多空出来\(n-1\)\(([1,1,1,1,2])\),但是使所有树高度相同为\(H+2\)不能在树的高度全是\(H\)的情况下只用\(n-1\)次操作实现.

二分答案的判断时考虑有x次机会使数的高度加2,有y次机会加1,使用能用+2就用+2的思路判断。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define int long long
const int N=301000; 
int w[N],a[N],n;
int read(){
	int sum=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		sum=sum*10+ch-'0';
		ch=getchar();
	}
	return sum*f;
}
bool judge(int x){
	int num_2=x/2;
	int num_1=x-num_2;
	for(int i=1;i<=n;i++){
		int num=min(num_2,a[i]/2);
		num_2-=num;
		num_1-=a[i]-num*2;
		if(num_1<0||num_2<0)return false;
	}
	return true;
}
signed main(){
	int T=read();
	while(T--){
		n=read();
		int Ans=1e18;
		int Mx=0;
		for(int i=1;i<=n;i++)w[i]=read(),Mx=max(Mx,w[i]);
		for(int j=0;j<=1;j++){
			int mx=j+Mx;
			for(int i=1;i<=n;i++)a[i]=mx-w[i];
			int L=0,R=1e18;
			int ans=R;
			while(L<=R){
				int mid=(L+R>>1);
				if(judge(mid)){
					ans=mid;
					R=mid-1;
				}
				else L=mid+1;
			}
			Ans=min(Ans,ans);
		}
		cout<<Ans<<endl;
	}
	return 0;
} 
posted @ 2022-04-12 20:42  Xu-daxia  阅读(161)  评论(0编辑  收藏  举报