zoukankan      html  css  js  c++  java
  • CF-985D.Sand Fortress(贪心、二分)

    CF传送门

    洛谷传送门


    解题思路

    总结一下,
    其实只有两种情况:

    • k,k-1,k-2,k-3,k-4,k-5,……,1(k<=h)+ 一堆高度为[1,k]
    • h,h+1,……,h+x,h+x-1,h+x-2,……,1 + 一堆高度为[1,h+x]

    贪心:k和x显然是越大越好。
    于是我们可以二分k和x,可以得出答案。
    注意的细节:
    等差数列求和需要 (h*(h+1)/2) ,而 (h<=1e18) ,直接乘会炸long long。
    所以我们可以一开始特判一下,因为(n<=1e18),所以若h>=1e9,一定是第一种情况,直接二分即可。

    AC代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    long long n,h; 
    bool check(long long x){
    	if(x*(x+1)/2>=n) return true;
    	return false;
    }
    bool check2(long long x){
    	if((h+x)*(x-h+1)/2+x*(x+1)/2>=n) return 1;
    	return 0; 
    }
    int main(){
    	cin>>n>>h;
    	if(h>=2e9||(h*(h+1)/2>=n-h)){
    		long long l=1,r=min((long long)2e9,h),mid=(l+r)/2;
    		while(l!=r){
    			if(check(mid)) r=mid;
    			else l=mid+1;
    			mid=(l+r)/2;
    		}
    		if(l*(l+1)/2<n) l++;
    		cout<<l<<endl;
    		return 0;
    	}
    	long long l=h,r=2e9,mid=(l+r)/2;
    	while(l!=r){
    		if(check2(mid)) r=mid;
    		else l=mid+1;
    		mid=(l+r)/2;
    	}
    	long long ans=(l-h)+l;
    	if((h+l)*(l-h+1)/2+l*(l+1)/2-l<n) ans++;
    	cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    bzoj 5455
    hdu 6705
    hdu 6706
    斜率优化
    bzoj3672
    bzoj1367
    bzoj2118
    bzoj2337
    Codeforces 1077D Cutting Out(二分答案)
    Codeforces 1079C Playing Piano(记忆化搜索)
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14775044.html
Copyright © 2011-2022 走看看