Codeforces 614D 二分
阿新 • • 發佈:2018-03-28
輸出 clu down lin sin ems DC spa 題意
D. Skills
題意:
給出 n, A, cf, cm, m,表示有 n 個技能,每個技能當前水平為 a[i] ,最高水平為 A ,有 m 個技能點,花費一個技能點可以使任意一個技能水平加一 (最高只能是 A)。
如果最後水平為 A 的技能有 x 個,最低的技能水平值為 y,定義權值為 cf*x+cm*y 。求可能的最高權值,並輸出最後每個技能的水平。
tags:
枚舉 x ,對當前 x 二分可能的最低水平值,check 時還要再二分一下。
// 614D #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005; int n; ll A, cf, cm, m, sum[N], b[N]; pair< ll, int >a[N]; bool check(ll y, ll m2, ll x) { int pos = lower_bound(a+1, a+1+n, MP(y,0)) - a; --pos; if(pos+x > n) pos=n-x; return m2 >= (y*pos-sum[pos]); } int main() { scanf("%d%lld%lld%lld%lld", &n, &A, &cf, &cm, &m); rep(i,1,n) scanf("%lld", &a[i].fi), a[i].se=i; sort(a+1, a+1+n); rep(i,1,n) sum[i]=sum[i-1]+a[i].fi; ll ans=0, ans1=0, ans2=a[1].fi; for(ll x=0; x<=n; ++x) { ll tmp = m - (A*x-(sum[n]-sum[n-x])); if(tmp < 0) continue; ll l=a[1].fi, r=A, mid, ret; while(l <= r) { mid = l+(r-l)/2; if(check(mid, tmp, x)) ret=mid, l=mid+1; else r=mid-1; } if(ans < cf*x+cm*ret) { ans = cf*x+cm*ret; ans1=x, ans2=ret; } } printf("%lld\n", ans); int pos = lower_bound(a+1, a+1+n, MP(ans2,0)) - a; --pos; if(pos+ans1 > n) pos = n-ans1; rep(i,1,pos) b[a[i].se] = ans2; rep(i,pos+1,n-ans1) b[a[i].se] = a[i].fi; rep(i,n-ans1+1,n) b[a[i].se] = A; rep(i,1,n) printf("%lld ", b[i]); return 0; }
Codeforces 614D 二分