[CF1328F] Make k Equal - 贪心

Solution

枚举选择一个中间点,计算把边上压到中间这条线上的答案

压的时候要考虑两边压和单边压的情况

(以下代码中的二分显得很累赘,纯粹为了偷懒而出现)

using namespace std;

#define int long long
const int N = 200005;

int n,k,a[N],pre[N],suf[N],ans=1e18;
map<int,int> mp;

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) {
        pre[i]=pre[i-1]+a[i];
    }
    for(int i=n;i>=1;--i) {
        suf[i]=suf[i+1]+a[i];
    }
    for(int i=1;i<=n;i++) mp[a[i]]++;
    for(auto i:mp) if(i.second>=k) {
        cout<<0<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++) {
        int x=a[i];
        int e=upper_bound(a+1,a+n+1,x)-lower_bound(a+1,a+n+1,x);
        int g=n-(upper_bound(a+1,a+n+1,x)-a)+1;
        int l=lower_bound(a+1,a+n+1,x)-a-1;
        int sg=suf[n-g+1];
        int sl=pre[l];
        int tmp=sg-g*x+l*x-sl-(n-k);
        ans=min(ans,tmp);
        if(n-l>=k) {
            int tx=sg-g*x-(n-l-k);
            ans=min(ans,tx);
        }
        if(n-g>=k) {
            int tx=l*x-sl-(n-g-k);
            ans=min(ans,tx);
        }
        //cout<<l<<" "<<e<<" "<<g<<endl;
    }
    cout<<max(0ll,ans);
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12579514.html