CF960B Minimize the error

CF960B Minimize the error

洛谷传送门

题意翻译

有两个长度均为 nnn 的序列 a,ba,ba,b,定义 cost(a,b){ m cost}(a,b)cost(a,b) :

cost(a,b)=∑i=1n(ai−bi)2{ m cost}(a,b)=sum_{i=1}{n}left(a_{i}-b_{i} ight){2} cost(a,b)=i=1∑n(ai−bi)2

现在必须恰好对 aaa 进行 k1k_1k1 次操作,对 bbb 进行 k2k_2k2 次操作。操作内容是将某一项加一或者减一。求操作后的最小 cost m costcost。

translated by @皎月半洒花。


题解:

一道还不错的贪心。

发现首先应该考虑差最大的,然后等到把它消成第二大的之后再同时削第二大的...以此类推。

这个贪心的正确性可以证明,因为平方增长,先消差大的肯定不亏。

那么上面的消除过程就可以模拟来解决。

直接优先队列,非常方便。

需要注意的是,由于操作相同,对于两个数列的操作可以加一起。

代码:

#include <bits/stdc++.h>
using namespace std;
#define iter(i, a, b) for(int i=(a); i<(b); i++)
#define rep(i, a) iter(i, 0, a)
#define rep1(i, a) iter(i, 1, (a)+1)
#define fi first
#define se second
#define pb push_back
#define ll long long
#define pii pair<int, int>
const int MOD = 1e9+7;
int a[1003], b[1003];
priority_queue<int, vector<int>> pq;
signed main() 
{
    int n, k1, k2; 
    scanf("%lld%lld%lld",&n,&k1,&k2);
    k1 += k2;
    rep(i, n) 
        scanf("%lld",&a[i]);
    rep(i, n) 
    {
        scanf("%lld",&b[i]);
        pq.push(abs(a[i]-b[i]));
    }
    while(k1--) 
    {
        int t = pq.top(); 
        pq.pop();
        if(t == 0) 
            pq.push(1);
        else 
            pq.push(t-1);
    }
    ll ans = 0;
    while(!pq.empty()) 
    {
        ans = ans + 1ll * pq.top() * pq.top();
        pq.pop();
    }
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/14012503.html