1. 程式人生 > >Minimum Inversion Number (線段樹解決逆序數問題)

Minimum Inversion Number (線段樹解決逆序數問題)

Minimum Inversion Number

線段樹解決逆序數問題

The inversion number of a given number sequence a1, a2, …, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

For a given sequence of numbers a1, a2, …, an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

a1, a2, …, an-1, an (where m = 0 - the initial seqence) a2, a3, …, an, a1 (where m = 1) a3, a4, …, an, a1, a2 (where m = 2) … an, a1, a2, …, an-1 (where m = n-1)

You are asked to write a program to find the minimum inversion number out of the above sequences.

Input The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.

Output For each case, output the minimum inversion number on a single line.

Sample Input

10
1 3 6 9 0 8 5 7 4 2

Sample Output

16
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=5005;
struct node{
	int sum,l,r;
}tr[maxn<<2];
int x[maxn];
void pushup(int m){
	tr[
m].sum=tr[m<<1].sum+tr[m<<1|1].sum; } void build(int m,int l,int r){ tr[m].l=l; tr[m].r=r; if(l==r){ tr[m].sum=0; return ; } int mid=(l+r)>>1; build(m<<1,l,mid); build(m<<1|1,mid+1,r); pushup(m); } void updata(int m,int inx,int val){ if(tr[m].l==inx&&tr[m].r==inx){ tr[m].sum+=val; return ; } int mid=(tr[m].l+tr[m].r)>>1; if(inx<=mid) updata(m<<1,inx,val); else updata(m<<1|1,inx,val); pushup(m); } int query(int m,int l,int r){ if(tr[m].l==l&&tr[m].r==r){ return tr[m].sum; } int mid=(tr[m].l+tr[m].r)>>1; int temp; if(r<=mid) temp=query(m<<1,l,r); else if(l>mid) temp=query(m<<1|1,l,r); else temp=query(m<<1,l,mid)+query(m<<1|1,mid+1,r); return temp; } int main(){ int n; while(~scanf("%d",&n)){ build(1,0,n); int sum=0; for(int i=0;i<n;i++){ scanf("%d",&x[i]); sum+=query(1,x[i]+1,n); updata(1,x[i],1); } int min=sum; for(int i=0;i<n-1;i++){ sum+=n-1-x[i]-x[i]; if(sum<min) min=sum; } printf("%d\n",min); } return 0; }