涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:
,其中 ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
输入描述 Input Description
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出描述 Output Description
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
根据距离的定义,最小的距离应该是数列a的第 i 大数 与数列b的第 i 大数分别做差,离散化后就变成了 ai 与 bi 相等,即求数列 a 基于 数列 b 的逆序对个数。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int size = 100010;
int num[size];
int templ[size];
int temp[size];
int ans = 0;
int n;
int a[size],b[size];
int cmp[size];
const int mod = 99999997;
int EF(int l,int r,int k,int *tmp)
{
while(r - l > 1)
{
int mid = (l + r) >> 1;
if(tmp[k] > templ[mid])
l = mid;
else if (tmp[k] < templ[mid])
r = mid;
else
return mid;
}
return r;
}
void lsha()
{
for(int i = 1 ; i <= n ; i ++)
templ[i] = a[i];
sort( templ+1 , templ+n+1 );
for(int i = 1 ; i <= n ; i ++)
a[i] = EF(0,n+1,i,a);
}
void lshb()
{
for(int i = 1 ; i <= n ; i ++)
templ[i] = b[i];
sort( templ+1 , templ+n+1 );
for(int i = 1 ; i <= n ; i ++)
b[i] = EF(0,n+1,i,b);
}
void merge(int l,int r)
{
if(l == r)
return ;
int mid = (l + r) >> 1;
merge(l,mid) , merge(mid+1,r);
int ll = l , rr = mid + 1 , p = ll;
while(ll <= mid || rr <= r)
{
if(rr > r || (ll <= mid && cmp[a[ll]] <= cmp[a[rr]]))
temp[p++] = a[ll++];
else
{
temp[p++] = a[rr++];
ans += mid - ll + 1;
ans %= mod;
}
}
for(int i = l ; i <= r ; i ++)
a[i] = temp[i];
}
int main()
{
int n;
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]);
lsha();
memset(templ,0,sizeof(templ));
lshb();
for(int i = 1 ; i <= n ; i ++)
cmp[b[i]] = i;
merge(1,n);
printf("%d",ans%mod);
return 0;
}
传送门 :
codevs 3286
tyvj 2515