您的位置:首页 > 其它

CSUACM月赛1971

2017-07-29 21:20 281 查看
看到感觉就是最大和最小匹配挺符合人类思维的就写了。然而题解证明很强。
这个问题是经典的贪心。$ ans
= (a_i - b_j)^2 ,我们展开它得到 ans
= a_i^2 + b_i^2$ - ***2 * ∑ai*bj。前两部分都是固定的,所以要使得答案尽量大,我们应该使得∑ai * bj尽量小。可以猜想这么个结论:a中最大的和b中最小的匹配,a中次大的与b中次小的匹配……这种匹配是最优的。证明使用排序不等式。倒序>=乱序>=顺序

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 100010

using namespace std;

int n,ans;
int a[maxl],b[maxl];

bool cmp(const int &x,const int &y)
{
return x>y;
}

void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
sort(a+1,a+1+n,cmp);
sort(b+1,b+1+n,cmp);
}

void mainwork()
{
ans=0;
int l1=1,l2=1,r1=n,r2=n;
for(int i=1;i<=n;i++)
{
if((a[l1]-b[r2])*(a[l1]-b[r2])>(a[r1]-b[l2])*(a[r1]-b[l2]))
{
ans+=(a[l1]-b[r2])*(a[l1]-b[r2]);
l1++;r2--;
}
else
{
ans+=(a[r1]-b[l2])*(a[r1]-b[l2]);
l2++;r1--;
}
}
}

void print()
{
printf("%d\n",ans);
}

int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: