nyoj 117 找到的倒数 【树阵】+【分离】

这个问题的解决方案是真的很不错!!!


思路:建立一个结构体包括val和id。 val就是输入的数,id表示输入的顺序。然后依照val从小到大排序。假设val相等。那么就依照id排序。

假设没有逆序的话,肯定id是跟i(表示拍好后的顺序)一直一样的。假设有逆序数。那么有的i和id是不一样的。

所以,利用树状数组的特性。我们能够简单的算出逆序数的个数。

假设还是不明确的话举个样例。(输入4个数)

输入:9 -1 18 5

输出 3.

输入之后相应的结构体就会变成这样

val:9 -1 18 5

id:  1  2  3  4

排好序之后就变成了

val :  -1 5 9 18

id:      2 4  1  3

之后再利用树状数组的特性就能够解决这个问题了。


注意:id 要从1開始。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define M 1000005
using std::sort;
struct node{
	int id, val;
}s[M];
int c[M], n;
int cmp(node a, node b){
	if(a.val != b.val) return a.val < b.val;
	return a.id<b.id;
}

int lowbit(int x){
	return x&(-x);
}

int getsum(int x){
	int sum = 0;
	while(x){
		sum += c[x];
		x -= lowbit(x);
	}
	return sum;
}

void add(int x){
	while(x <= M){
		c[x]++;
		x += lowbit(x);
	}
} 
int main(){
	int t, i;
	scanf("%d", &t);
	while(t --){
		scanf("%d", &n);
		for(i = 1; i<= n; i ++){
			scanf("%d", &s[i].val);
			s[i].id = i;
			//c[i] = 0;
		}
		memset(c, 0, sizeof(int)*(n+1));
		sort(s+1, s+n+1, cmp);
		long long ans = 0;
		for( i = 1; i <= n; i ++){
			add(s[i].id);  //和以下的不能互换
			ans += (i-getsum(s[i].id));  //这里是(i-getsum(s[i].id))
		}
		printf("%lld
", ans);
	}
	return 0;
}        

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=117

版权声明:本文博客原创文章,博客,未经同意,不得转载。

原文地址:https://www.cnblogs.com/lcchuguo/p/4710762.html