Minimum Inversion Number HDU - 1394 (line segment tree inversion number)

Minimum Inversion Number

Topic link: HDU-1394
There are many ways to find the inverse ordinal, one can be directly violent, the complexity of O(n^2), the second can be found by merge sort, the complexity of O(nlogn), and
now I have learned the line segment The tree can also be calculated by the line segment tree, the complexity of O(nlogn);
the first two methods will not be discussed, but only the method of using the segment tree to find the inverse number;
9 2 8 3 6 7 5 The inverse number of this sequence It's 12, how did it come out?
Look at 9 first, there is no larger number in front, contribute 0,
2, there is a larger number in front, contribute 1,
8, contribute 1; 3 contribute 2; 6 contribute 2; 7 contribute 2; 5 contribute 4, A total of 12;
it can be seen that it is only necessary to find out how many numbers larger than him have been written before writing each number;
we can first build an empty line segment tree, the nodes are 1~n, and each write Before the next number, check the position of the number and how many numbers are written after it, and then record the number;
this question requires to find out what is the smallest inverse number in the given sequence in different order, such as 2 8 7 4 3 Different permutations can be 8 7 4 3 2 or 7 4 3 2 8. . . . . .
If a sequence is 0~n-1:
when a number i is at the beginning of the sequence, there are only i numbers smaller than it in the sequence, and when it moves to the end of the sequence, there are ni-1 numbers in front of it that are much larger than it ;
so the reverse number of each transfer changes to sum=sum-i+n-1-i;
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 5010;
int n;
int a[maxn];
struct node{
	int left, right, x;
}tree[maxn<<2];
void build(int m, int l, int r){
	tree[m].left=l;
	tree[m].right=r;
	if(l==r){
		tree[m].x=0;
		return;
	}
	int mid=(l+r)>>1;
	build(m<<1, l, mid);
	build(m<<1|1, mid+1, r);
	tree[m].x=tree[m<<1].x+tree[m<<1|1].x;
}
void update(int m, int a){
	if(tree[m].left==a&&tree[m].right==a){
		tree[m].x++;
		return;
	}
	int mid=(tree[m].left+tree[m].right)>>1;
	if(a<=mid) update(m<<1, a);
	else update(m<<1|1, a);
	tree[m].x=tree[m<<1].x+tree[m<<1|1].x;
}
int query(int m, int l, int r){
	if(tree[m].left==l&&tree[m].right==r){
		return tree[m].x;
	}
	int sum1=0, sum2=0;
	int mid=(tree[m].left+tree[m].right)>>1;
	if(r<=mid) return query(m<<1, l, r);
	else if(l>mid) return query(m<<1|1, l, r);
	return query(m<<1, l, mid)+query(m<<1|1, mid+1, r);
}
int cnt[maxn], sum=0;
int main(){
	while(~scanf("%d", &n)){
		build(1, 1, n);
		sum=0;
		for(int i=1; i<=n; i++){
			scanf("%d", &a[i]);
			sum+=query(1, a[i]+1, n);//Query first and then update; because the input value is 0~n-1, and the node value is 1~n, so it is one position backward;
			update(1, a[i]+1);
		}
		int ans = sum;
		for(int i=1; i<=n; i++){
			//printf("i:%d   sum:%d\n", i, sum);
			sum=sum-a[i]+n-a[i]-1;
			years=min(years, sum);	
		}
		printf("%d\n", ans);
	}
	return 0;
}



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325783003&siteId=291194637