这还是一道比较简单的题目,稍微想一下就可以解决。终于有NOIP难度的题目了
首先我们看那个∑(ai-bi)^2的式子,发现这个的最小值就是排序不等式
所以我们只需要改变第一组火柴的顺序,使它和第二组火柴相对应(即大的对大的,小的对小的)
然后我们离散一下,找出每一个数该去的位置
然后注意到这里的交换方式,相邻交换,这就直接转化为求逆序对的问题了
然后直接上树状数组即可
CODE
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005,mod=99999997;
struct data
{
int x,num;
}a[N],b[N];
int tree[N],r[N],n,ans;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline bool comp(data a,data b)
{
return a.x<b.x;
}
inline void inc(int &x,int y)
{
if ((x+=y)>=mod) x-=mod;
}
inline int lowbit(int x)
{
return x&(-x);
}
inline int get(int x)
{
int tot=0;
while (x) inc(tot,tree[x]),x-=lowbit(x);
return tot;
}
inline void add(int x)
{
while (x<=n) inc(tree[x],1),x+=lowbit(x);
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i;
for (read(n),i=1;i<=n;++i)
read(a[i].x),a[i].num=i;
for (i=1;i<=n;++i)
read(b[i].x),b[i].num=i;
sort(a+1,a+n+1,comp);
sort(b+1,b+n+1,comp);
for (i=1;i<=n;++i)
r[a[i].num]=b[i].num;
for (i=1;i<=n;++i)
{
inc(ans,get(n)-get(r[i]));
add(r[i]);
}
printf("%d",ans);
return 0;
}