http://www.lydsy.com/JudgeOnline/problem.php?id=4989php
上下有兩個位置分別對應的序列A、B,長度爲n,
兩序列爲n的一個排列。當Ai == Bj時,上下會連一條邊。
你能夠選擇序列A或者序列B進行旋轉任意K步,
如 3 4 1 5 2 旋轉兩步爲 5 2 3 4 1。
求旋轉後最小的相交的線段的對數。c++
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.數組
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).ide
5spa
5
4
1
3
2
1
3
2
5
4code
0get
樹狀數組,而後推一下移動一個數的代價就行了。input
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+7; int d[maxn],c[maxn]; int a[maxn],b[maxn],a2[maxn],b2[maxn]; int n; int lowbit(int x){ return x&(-x); } void update(int x,int v){ for(int i=x;i<maxn;i+=lowbit(i)){ d[i]+=v; } } long long get(int x){ long long ans = 0; for(int i=x;i;i-=lowbit(i)){ ans+=d[i]; } return ans; } long long solve(int a[],int b[]){ memset(d,0,sizeof(d)); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++){ c[b[i]]=i; } for(int i=1;i<=n;i++){ a[i]=c[a[i]]; } long long ans = 0; for(int i=1;i<=n;i++){ ans+=(n-a[i])-get(a[i]); update(a[i],1); } long long ans2 = ans; for(int i=n;i>=1;i--){ ans=ans-(n-a[i])+(a[i]-1); ans2=min(ans2,ans); } return ans2; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); a2[i]=a[i]; } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); b2[i]=b[i]; } cout<<min(solve(a,b),solve(b2,a2))<<endl; }