poj 2299 Ultra-QuickSort 求逆序对

题目大意:

给你一组序列,求得该组序列的逆序对;

解题思路:

这道题目可以用树状数组也可以用线段树;
在插入的过程中不断的查询当前位置之前的数字个数和,然后用当前的位置减去这个和即可,因为如果查找到比你小的数,则说明它们在序列中当前位置的前面,而现在插入的个数为当前数字的位置,所以用插入的个数减去比当前位置小的个数,即为在当前位置比当前位置数字大的已经插入的数字的个数,即逆序对;
但是这道题目需要注意的是数据的范围是0-999999999,所以需要离散化;
离散的方法,记录原来的位置,然后从小到大排序,然后按照次序赋予当前每个数的位置,然后按照原来的顺序插入当前的位置即可;感觉好绕,看代码!!!!!!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 500010
int n;
int c[maxn];
int now[maxn];
struct Node{
	int pos;
	int val;
	Node(){}
	Node(int a,int b):pos(a),val(b){}
	bool operator <(const Node &t)const{return val<t.val;}
}node[maxn];
int lowbit(int x)
{
	return x&(-x);
} 
void updata(int x)
{
	while(x<=n)
	{
		c[x]+=1;
		x+=lowbit(x);
	}
}
int getsum(int x)
{
	long long sum=0;
	while(x>0)
	{
		sum+=c[x];
		x-=lowbit(x);
	}
	return sum;
}
int main()
{
	while(scanf("%d",&n),n)
	{
		long long ans=0;
		memset(c,0,sizeof(c));
		for(int i=1;i<=n;i++)
		{
			int num;
			scanf("%d",&num);
			node[i]=Node(i,num);
		}
		sort(node+1,node+n+1);
		for(int i=1;i<=n;i++)
		now[node[i].pos]=i;
		for(int i=1;i<=n;i++)
		{
			ans+=i-1-getsum(now[i]);
			updata(now[i]);
		}
		printf("%lld\n",ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值