BZOJ 4989: [Usaco2017 Feb]Why Did the Cow Cross the Road 逆序对

4989: [Usaco2017 Feb]Why Did the Cow Cross the Road

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 21  Solved: 11
[Submit][Status][Discuss]

Description

Why did the cow cross the road? We may never know the full reason, but it is certain that Farmer Joh n's cows do end up crossing the road quite frequently. In fact, they end up crossing the road so oft en that they often bump into each-other when their paths cross, a situation Farmer John would like t o remedy.Farmer John raises N breeds of cows (1≤N≤100,000), and each of his fields is dedicated to  grazing for one specific breed; for example, a field dedicated to breed 12 can only be used for cow s of breed 12 and not of any other breed. A long road runs through his farm. There is a sequence of  NN fields on one side of the road (one for each breed), and a sequence of N fields on the other side  of the road (also one for each breed). When a cow crosses the road, she therefore crosses between t he two fields designated for her specific breed.Had Farmer John planned more carefully, he would hav e ordered the fields by breed the same way on both sides of the road, so the two fields for each bre ed would be directly across the road from each-other. This would have allowed cows to cross the road  without any cows from different breeds bumping into one-another. Alas, the orderings on both sides  of the road might be different, so Farmer John observes that there might be pairs of breeds that cro ss. A pair of different breeds (a,b) is "crossing" if any path across the road for breed aa must int ersect any path across the road for breed bb.Farmer John would like to minimize the number of crossi ng pairs of breeds. For logistical reasons, he figures he can move cows around on one side of the ro ad so the fields on that side undergo a "cyclic shift". That is, for some 0≤k<N, every cow re-locat es to the field kk fields ahead of it, with the cows in the last kk fields moving so they now popula te the first kk fields. For example, if the fields on one side of the road start out ordered by bree d as 3, 7, 1, 2, 5, 4, 6 and undergo a cyclic shift by k=2, the new order will be 4, 6, 3, 7, 1, 2,  5. Please determine the minimum possible number of crossing pairs of breeds that can exist after an  appropriate cyclic shift of the fields on one side of the road.上下有两个位置分别对应的序列A、B,长度为n, 两序列为n的一个排列。当Ai == Bj时,上下会连一条边。 你可以选择序列A或者序列B进行旋转任意K步, 如 3 4 1 5 2 旋转两步为 5 2 3 4 1。 求旋转后最小的相交的线段的对数。

Input

The first line of input contains N. 
The next N lines describe the order, by breed ID, of fields on one side of the road; 
each breed ID is an integer in the range 1…N. 
The last N lines describe the order, by breed ID, of the fields on the other side of the road.

Output

Please output the minimum number of crossing pairs of breeds after a cyclic shift of the 
fields on one side of the road (either side can be shifted).

Sample Input

5
5
4
1
3
2
1
3
2
5
4

Sample Output

0

定义qi为ai在b中的位置,交叉对就是q的逆序对。

只要求出逆序对,之后每次把最后的移到最前面,维护逆序对个数就可以了。

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;

typedef long long ll;

inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
void print(ll x)
{if(x<0)x=-x,putchar('-');if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=100100;

ll ans=1ll*N*N;

int n;

int bit[N];

inline void modify(int x)
{for(;x<=n;x+=(x&-x))bit[x]++;}

inline int query(int x)
{int res=0;for(;x;x-=(x&-x))res+=bit[x];return res;}

int p[N],pos[N];

void solve(int *a,int *b)
{
	register int i;
	ll res=0;
	for(i=1;i<=n;++i)pos[a[i]]=i;
	for(i=1;i<=n;++i)p[i]=pos[b[i]];
	for(i=n;i;i--){res+=query(p[i]);modify(p[i]);}
	ans=min(res,ans);
	for(i=n;i;--i)
	{
		res-=n-p[i];res+=p[i]-1;
		ans=min(ans,res);
	}
}

int a[N],b[N];

int main()
{
	n=read();
	register int i;
	for(i=1;i<=n;++i)a[i]=read();for(i=1;i<=n;++i)b[i]=read();
	solve(a,b);memset(bit+1,0,sizeof(int)*n);solve(b,a);
	print(ans);puts("");
	return 0;
}
/*
5
5 4 1 3 2
1 3 2 5 4

0
*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值