续续 Codeforces 613 B Skills

题目传送门:http://codeforces.com/contest/613/problem/B
Two pointers的解法,就是喜欢优美的解法和装逼的姿势!!
首先存储的方式逼格就很高,比起之前的那种分着记录每一项高的多!
然后就是双指针法,外层指针指的是后几个满血的,内指针指的是前几个剩余钱能够满足的能力值最小的,因为随着满血的skill增加,内指针必定是要不断减小的,所以完美地O(n)解决此问题!!!
相比之下还是Two pointers的解法更优一点!
附上优美的英文注释

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAX=1e5+9;
pair<ll,ll> a[MAX];//store initial skill and id
ll sum[MAX],res[MAX],n,cf,cm,m,A;   
pair<ll,pair<ll,ll>> ans;// store sth we need
int main()
{
    ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>A>>cf>>cm>>m;
    for(int i=1;i<=n;i++) cin>>a[i].first,a[i].second=i;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i].first;
    ll p=n;
    for(ll i=0;i<=n;i++)
    {
        ll d=m-i*A+sum[n]-sum[n - i];
        if(d<0) break;
        p=min(p,n-i);
        while(p>1 && d<p*a[p].first-sum[p]) p--;
        d-=p*a[p].first-sum[p];
        ll k=min(A,i==n?A:(a[p].first+d/p));
        //store ans,pos,minleval
        ans=max(ans,{i*cf+k*cm,{i,k}});
    }
    cout<<ans.first<<'\n';
    for(int i=0;i<ans.second.first;i++) a[n-i].first=A;
    for(int i=1;i<=n;i++) a[i].first=max(a[i].first,ans.second.second),res[a[i].second]=a[i].first;
    for(int i=1;i<=n;i++) cout<<res[i]<<" ";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值