【NOIP2013提高组】火柴排队

题目大意:给你两个有序数组a,b并定义a,b间的距离为∑(ai-bi)^2,要求交换a或者b中的某些元素的位置使得a,b间距离最小。

由于∑(ai-bi)^2=∑(ai^2)+∑(bi^2)-2*∑aibi;而由于题目给定了ai,bi的值,所以∑(ai^2)、∑(bi^2)是定值,要求原式最小就需要∑aibi最大。

而根据排序不等式原理,∑aibi最大值是ai,bi的顺序和。

所以先把ai按照高度排好序,bi也按照高度排好序。题目所求就是排好序的ai和bi编号要求1~6一一对应时的排序次数。

用一个数组记录ai,bi编号间的对应关系,再求逆序对个数即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<cstring>
#define mo 99999997
#define maxn 100010
using namespace std;
typedef long long LL;
int n;
struct data
{
	int v,id;
}A[maxn],B[maxn];

bool cmp(data a,data b)
{
	return a.v<b.v;
}

int x[maxn],t[maxn];

LL merge_sort(int x,int y,int *a)
{
	if(x>=y)return 0;
	int m=x+y>>1;
	LL t1=merge_sort(x,m,a);
	LL t2=merge_sort(m+1,y,a);
	LL t3=0;
	
	int i=x,j=m+1,k=x;
	while(i<=m && j<=y)
	{
		if(a[i]>a[j])
		{
			t[k++]=a[j++];
			t3=(t3%mo+(m-i+1)%mo)%mo;
		}
		else
		{
			t[k++]=a[i++];
		}
	}
	
	while(i<=m)t[k++]=a[i++];
	while(j<=y)t[k++]=a[j++];
	
	for(int i=x;i<=y;i++)
	a[i]=t[i];
	
	return (t1+t2+t3)%mo;
}

int main()
{
	//freopen("match.in","r",stdin);
	//freopen("match.out","w",stdout);
	
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&A[i].v);
		A[i].id=i;
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&B[i].v);
		B[i].id=i;
	}
	
	sort(A+1,A+n+1,cmp);
	sort(B+1,B+n+1,cmp);
	
	for(int i=1;i<=n;i++)
	x[A[i].id]=B[i].id;
	
	LL ans=merge_sort(1,n,x);
	
	cout<<ans<<endl;
	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值