zoukankan      html  css  js  c++  java
  • CF505E Mr. Kitayuta vs. Bamboos 题解

    Codeforces
    Luogu

    Description.

    给定一个长度为 \(n\) 的序列,每个位置由两个权值,\(a_i(a_i>0)\)\(h_i\)
    \(m\) 轮操作,每轮操作中,你可以选择 \(K\) 个不同的位置,把它们分别变成变成 \(\max\{a_i-p,0\}\)
    最小化最后序列最大值。

    Solution.

    想到二分了,想到倒序了,但是没提炼出性质。

    最小化最大值,直接一个二分,设答案为 \(x\)
    然后正着做很难,反者做就比较容易。
    问题转化为,刚开始都等于 \(x\),每次可以选 \(K\)\(+=p\),每次自动会 \(-=a_i\),问最后能否 \(\ge h_i\)
    同时,因为原题中有一个 \(\max\),所以要保证 \(-=a_i\)\(\ge 0\)就是这个性质没发现
    这个就很清真了,直接做也可以,提取性质也可以。
    直接做的话直接考虑用一个堆维护到最后还需要加的东西。
    贪心地考虑,一个数在前面加和后面加除了可能会 \(-\) 之外没区别。
    所以我们贪心地把前 \(K\) 个最先变 \(-\) 的加上 \(p\) 即可。

    同时,也可以发现,原题分两部分。
    第一部分是不能取到 \(-\),第二部分是最后要 \(\ge h_i\)
    我们考虑算出第一部分最多要 \(+\) 几个 \(p\),然后第二部分扫一遍。
    第一部分和另一种方法其实类似,直接用堆扫一遍即可。

    Coding.

    点击查看方法1的清新代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }/*}}}*/
    int n,m,K,p,a[100005],cnt[100005],h[100005];
    inline char check(ll x)
    {
    	priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q;
    	for(int i=1;i<=n;i++) if(x-h[i]<1ll*m*a[i]) q.push(make_pair(x/a[i],i)),cnt[i]=0;
    	for(int z=1;z<=m&&!q.empty();z++) for(int j=1;j<=K&&!q.empty();j++)
    	{
    		int i=q.top().second;if(q.top().first<z) return 0;else q.pop(),cnt[i]++;
    		if(x+1ll*cnt[i]*p<h[i]+1ll*m*a[i]) q.push(make_pair((x+1ll*cnt[i]*p)/a[i],i));
    	}
    	return q.empty();
    }
    int main()
    {
    	read(n),read(m),read(K),read(p);ll l=0,r=1e18,rs=r;
    	for(int i=1;i<=n;i++) read(h[i]),read(a[i]),l=max(l,(ll)a[i]),r=max(r,1ll*n*h[i]+a[i]);
    	while(l<=r) {ll md=(l+r)>>1;if(check(md)) r=md-1,rs=md;else l=md+1;}
    	return printf("%lld\n",rs),0;
    }
    
    点击查看方法2的复杂代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }/*}}}*/
    int n,m,K,p,a[100005],cnt[100005],h[100005];
    inline char check(ll x)
    {
    	priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q;
    	for(int i=1;i<=n;i++) if((x-h[i])/a[i]<m) q.push(make_pair(x/a[i],i)),cnt[i]=0;
    	int tot=0;for(int z=1;z<=m&&!q.empty();z++) for(int j=1;j<=K&&!q.empty();j++)
    	{
    		int i=q.top().second;if(q.top().first<z) return 0;else q.pop(),cnt[i]++;
    		ll vl=(x+1ll*cnt[i]*p)/a[i];tot++;if(vl<m) q.push(make_pair(vl,i));
    	}
    	for(int i=1;i<=n;i++) if(x+1ll*cnt[i]*p-1ll*m*a[i]<h[i])
    		{tot+=(h[i]-x-1ll*cnt[i]*p+1ll*m*a[i]+p-1)/p;if(tot>m*K) return 0;}
    	return 1;
    }
    int main()
    {
    	read(n),read(m),read(K),read(p);ll l=0,r=1e18,rs=r;
    	for(int i=1;i<=n;i++) read(h[i]),read(a[i]),l=max(l,(ll)a[i]),r=max(r,1ll*n*h[i]+a[i]);
    	while(l<=r) {ll md=(l+r)>>1;if(check(md)) r=md-1,rs=md;else l=md+1;}
    	return printf("%lld\n",rs),0;
    }
    
  • 相关阅读:
    [置顶] kubernetes资源对象--ResourceQuotas
    [置顶] kubernetes资源对象--limitranges
    [置顶] kubernetes--Init Container
    Kubernetes:理解资源的概念
    [置顶] kubernetes资源对象--Horizontal Pod Autoscaling(HPA)
    [置顶] kubernetes资源对象--ConfigMap
    为什么我不使用Kubernetes的Ingress
    ajax遍历数组对象
    解决Myeclipse ctrl+h带来的困扰
    The markup in the document following the root element must be well-formed. Quartz.xml .......
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15076854.html
Copyright © 2011-2022 走看看