16-求逆序数(树状数组)

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

eg:
原序列: 4 5 1 3 2
标准序列:1 2 3 4 5
逆序数 :7

可以用树状数组做:讲解:00:58 : 00   https://www.nowcoder.com/study/live/153/11/1

 

 对于标准的1到n的数字:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int sum[50005];  //sum[x]表示的是区间为2^k个元素的和,k为x的二进制末尾0的个数,以为最后一个元素为a[x], 
int n;			 //所以sum[x] = a[n - 2^k + 1] + ...+ a[x]; 看图理解	

void update(int pos, int val){
	while(pos <= n){  //一直更新到最后 
		sum[pos] += val;
		pos += (pos & (-pos));  //pos && (-pos)找到pos二进制末尾一个1 
	}
}

int query(int pos){
	int ans = 0;
	while(pos > 0){   //一直加到0 
		ans += sum[pos];
		pos -= (pos & (-pos));
	}
	return ans;
}
int main(){
	int ans = 0, x;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		scanf("%d", &x);
		update(x, 1);
		for(int i = 1; i <= n; i++){
			cout << sum[i] << " ";
		}
		cout << endl;
		int temp = query(x);
		ans += x - temp;
		cout << temp << "tem" <<endl;
	}
	printf("%d
", ans);
	return 0;
}

  

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
int sum[50005];  //sum[x]表示的是区间为2^k个元素的和,k为x的二进制末尾0的个数,以为最后一个元素为a[x], 
int n;			 //所以sum[x] = a[n - 2^k + 1] + ...+ a[x]; 看图理解	
struct node{
	int pos, x;  //pos:记录输入的位置,x:值 
}a[100005];
int b[100005];

bool cmp(node x, node y){
	return x.x < y.x;
}

void update(int pos, int val){
	while(pos <= n){  //一直更新到最后 
		sum[pos] += val;
		pos += (pos & (-pos));  //pos && (-pos)找到pos二进制末尾一个1 
	}
}

int query(int pos){
	int ans = 0;
	while(pos > 0){   //一直加到0 
		ans += sum[pos];
		pos -= (pos & (-pos));
	}
	return ans;
}
int main(){
	long long ans = 0, x;  //int错了 
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		scanf("%d", &a[i].x);
		a[i].pos = i;
	}
	sort(a + 1, a + n + 1, cmp);
	for(int i = 1; i <= n; i++){
		b[a[i].pos] = i;
	}
	for(int i = 1; i <= n; i++){
		x = b[i];
		update(x, 1);
		int temp = query(x);
		ans += x - temp;
	}
	printf("%d
", ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/8469175.html