• CF505E-Mr. Kitayuta vs. Bamboos【贪心,二分】


    正题

    题目链接:https://www.luogu.com.cn/problem/CF505E


    题目大意

    开始一个长度为(n)的序列(h)(m)天每天你可以(k)次选择一个(h_i)让它等于(h_i=max{h_i-p,0}),然后结束时让每个(h_i=h_i+a_i),要求使得最后最大的(h)值最小。

    (1leq nleq 10^5,1leq mleq 5 imes 10^3,1leq kleq 10)


    解题思路

    这个好像是以前WC还是APIO讲课的题了。

    首先最大值最小直接上二分,然后考虑贪心做。

    不过正着做不太好做,考虑倒着。首先因为每次减法减去的值都是一样的,所以如果有一株的高度大于(p)那么我们显然没有必要剪高度小于(p)的,因为这样会浪费。

    设答案为(H),那么开始我们就让所有草的高度都是(H),然后每次所有的草高度减少(a_i),然后你可以(k)次拔高一棵草的高度(k)。要求全程没有草的高度小于零且最后第(i)棵草的高度都不小于(h_i)

    那么考虑如果一棵草不用再管高度都不会小于(h_i)那么显然不需要管这棵了,否则剪它肯定不会,为了满足条件我们肯定是减去最快小于(0)的那棵草。

    时间复杂度:(O(log L(nlog n+mklog n)))


    (code)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ll long long
    #define mp(x,y) make_pair(x,y)
    using namespace std;
    const ll N=1e5+10;
    ll n,m,k,p,h[N],a[N],w[N];
    priority_queue<pair<ll,ll> > q;
    bool check(ll H){
    	while(!q.empty())q.pop();
    	for(ll i=1;i<=n;i++)
    		if(H-a[i]*m<h[i])w[i]=H,q.push(mp(-H/a[i],i));
    	for(ll i=1;i<=m;i++)
    		for(ll j=1;j<=k;j++){
    			if(q.empty())return 1;
    			ll z=-q.top().first;
    			ll x=q.top().second;
    			if(z-i<0)return 0;
    			q.pop();w[x]+=p;
    			if(w[x]-a[x]*m<h[x])
    				q.push(mp(-w[x]/a[x],x));
    		}
    	if(q.empty())return 1;
    	return 0;
    }
    signed main()
    {
    	scanf("%lld%lld%lld%lld",&n,&m,&k,&p);
    	for(ll i=1;i<=n;i++)scanf("%lld%lld",&h[i],&a[i]);
    	ll l=0,r=1e9*(m+10);
    	while(l<=r){
    		ll mid=(l+r)>>1;
    		if(check(mid))r=mid-1;
    		else l=mid+1;
    	}
    	printf("%lld
    ",l);
    	return 0;
    }
    
  • 相关阅读:
    第3章 对象基础
    [置顶] CSDN博客客户端(非官方)
    javascript 修改对象
    Print2Flash出现"System Error. Code:1722. RPC服务器不可用."错误解决办法
    ConfigHelper 配置文件辅助类
    多个委托方法的顺序执行
    javascript Table
    字符串拼接方式(待商榷)
    CSDN博客客户端(非官方)
    javascript 对象继承
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15353456.html
Copyright © 2020-2023  润新知