1. 程式人生 > >960B Minimize the error (思維,貪心)

960B Minimize the error (思維,貪心)

題目大意:

      給你兩個陣列a,b,你可以對a陣列進行k1次操作,每次操作可以選擇a陣列的一個元素對其+1或-1,對b陣列進行k2次操作,每次操作可以選擇b陣列的一個元素對其+1或-1,最後計算,問E的最小值是多少

題解:

      我們肯定要優先把差距大的給縮小,因為差距大的一平方之後差距會更大,就比如陣列元素個數為4,a1和b1,a2和b2,a3和b3的差距都為1,a4和b4差距為3,而我們只能進行k1+k2=3次操作的話,肯定要優先對a4和b4縮小差距,前三個的差距和不過是3*1^{2}=3,而a4和b4的話3^{2}=9

      至於k1,k2必須要全用完的問題,完全可以選擇一個數對它加一再減一,所以最後剩下的k1+k2,如果是奇數,就在最後結果+1,偶數的話完全可以兩兩操作抵消掉

     也可以用優先佇列來做

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
struct node
{
    ll a,b,c;
} a[1010];
bool cmp(node a,node b)
{
    return a.c>b.c;
}
int main()
{
    int n,k1,k2;
    cin>>n>>k1>>k2;
    for(int i=0; i<n; i++)
        cin>>a[i].a;
    for(int i=0; i<n; i++)
    {
        cin>>a[i].b;
        a[i].c=abs(a[i].b-a[i].a);
    }
    sort(a,a+n,cmp);
    bool flag=1;
    while(k1 && flag)
    {
        flag=0;
        if(a[0].c>0)
        {
            a[0].c--;
            k1--;
            flag=1;
        }
        sort(a,a+n,cmp);
    }
    flag=1;
    while(k2 && flag)
    {
        flag=0;
        if(a[0].c>0)
        {
            a[0].c--;
            k2--;
            flag=1;
        }
        sort(a,a+n,cmp);
    }
    ll ans(0);
    for(int i=0; i<n; i++)
        ans+=a[i].c*a[i].c;
    ans+=((k1+k2)&1);
    cout<<ans<<"\n";
    
    return 0;
}