https://www.luogu.org/problem/P1966
分析问题:要求min{∑(ai2+bi2-2aibi)}=min{∑ai2+∑bi2-∑2aibi},我们需要使ai*bi的值最大即可
关键1:排序不等式的定义就是对于这样两个有序数列,它们的 逆序乘积和<=乱序乘积和<=顺序乘积和
关键2:参考洛谷大佬题解
这样问题就与求逆序对很相似了;
进行离散化即可,然后问题就变成求离散后的数组恢复升序,所需要的交换次数
树状数组代码,当然也可以用归并排序做
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <map>
#include <math.h>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <deque>
using namespace std;
const int N=1000010;
const int mod=99999997;
int tree[N],b[N],a[N],Ans[N];
int n,m=0;
struct sa
{
int date,pos;
}up[N],down[N];
int cmp(sa a,sa b)
{
return a.date<b.date;
}
void update(int x,int y)
{
for(;x<=n;x+=(x&-x))
tree[x]+=y,tree[x]%=mod;
}
int sum(int x)
{
int ans=0;
for(;x;x-=(x&-x)) {
ans += tree[x],ans%=mod;
}
return ans%mod;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&up[i].date);
up[i].pos=i;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&down[i].date);
down[i].pos=i;
}
sort(up+1,up+n+1,cmp);
sort(down+1,down+n+1,cmp);
for(int i=1;i<=n;i++)//离散化
{
a[up[i].pos]=down[i].pos;
}
int ans=0;
for(int i=1;i<=n;i++)
{
update(a[i],1);
ans+=(i-sum(a[i]))%mod;
ans%=mod;
}
printf("%d\n",ans%mod);
return 0;
}