看到感觉就是最大和最小匹配挺符合人类思维的就写了。然而题解证明很强。
这个问题是经典的贪心。$ 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;
}