Minimum Inversion Number HDU - 1394(樹狀數組/權值線段樹求逆序對)

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<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

struct sg{
	int l,r,v;
	#define l(x) t[x].l
	#define r(x) t[x].r
	#define v(x) t[x].v 
}t[10009*8];

int a[10009];



void build(int p,int l,int r){
	l(p)=l,r(p)=r,v(p)=0;
	if(l==r) return;
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
} 

void change(int p,int d){
	if(l(p)==r(p)){
		v(p)++;
		return;
	}
	int mid=(l(p)+r(p))/2;
	if(d<=mid) change(p*2,d);
	else change(p*2+1,d);
	v(p)=v(p*2)+v(p*2+1);
	}

int ask(int p,int l,int r){
	if(l<=l(p)&&r(p)<=r){
		return v(p);
	}
	int mid=(l(p)+r(p))/2;
	int ans=0;
	if(l<=mid) ans+=ask(p*2,l,r);
	if(r>mid) ans+=ask(p*2+1,l,r);
	return ans;
}



int main(){
	int n;
	while(~scanf("%d",&n)){
		build(1,1,n);
		int ans=0;
		for(int i=1;i<=n;i++){
			int ta;
			scanf("%d",&a[i]);
			a[i]++;
			ans+=ask(1,a[i],n);
			change(1,a[i]);
		}
		int minn=ans;
		for(int i=1;i<=n;i++){
			ans=ans-ask(1,1,a[i]-1)+ask(1,a[i]+1,n);
			minn=min(minn,ans);
		}
		printf("%d\n",minn);
	}
}
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int c[1000000];
int b[1000000];

int a[1000000];
int k;
	
void add(int i){
	for(;i<=k;i+=i&-i) c[i]+=1; 
}

ll ask(int i){
	ll sum=0;
	for(;i;i-=i&-i) sum+=c[i];
	return sum;
}

int main(){
	while(~scanf("%d",&k)){
		if(k==0) break;
		memset(c,0,sizeof(c));
		for(int i=1;i<=k;i++){
		 scanf("%d",&a[i]);
		 a[i]++;	
		}
		ll ans=0;
		for(int i=1;i<=k;i++) c[i]=0;
		for(int i=1;i<=k;i++){
			ans+=ask(k)-ask(a[i]);
			add(a[i]);
		}
		ll minnum=ans;
		for(int i=1;i<=k;i++){
			ans=ans-(a[i]-1)+k-a[i];
			minnum=min(minnum,ans);
		}
		printf("%lld\n",minnum);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章