Ultra-QuickSort POJ - 2299 (树状数组求逆序对数)

//已修改


#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

int n;

struct node

{

	int val, index;

}a[500010];//最初的输入 

int c[500010];//c[x]存储在区间 (x-lowbit(x)+1, x)小于等于x的个数 

bool cmp(struct node a,struct node b)

{

	return a.val<b.val;

}

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

void Update(int x)
{

	while(x<=n)

	{

		c[x]++; 

		x += lowbit(x);

	}

}

//计算的是当前区间(0, x)比x小的个数
int Sum(int x)

{

	int ans=0;

	while(x > 0)
	{

		ans += c[x];

		x -= lowbit(x);

	}

	return ans;

}

int main()

{

	while(~scanf("%d",&n) && n)
	{
		memset(c, 0, sizeof(c));

		for(int i=1;i<=n;i++)

		{

			scanf("%d", &a[i].val);

			a[i].index = i;//离散化 

		}

		sort(a+1, a+1+n, cmp);//val从小到大排序 

		long long int sum=0;//注意用long long,否则会WA 

        int b[n+5];
        
        for(int i=1; i<=n; i++){
        	b[a[i].index] = i;//离散对应
		}              



		for(int i=1;i<=n;i++){

			Update(b[i]);

			sum += i-Sum(b[i]); //i-Sum(x)计算的是当前比x大的个数,即逆序对数 

		}

		printf("%lld\n", sum);

	}

	return 0;

}

 

//以下版本在构造树状数组有问题,可能凑巧,,能过了例子......但是离散的方式不对.(即在对a[]离散过后,按照val值排序,还需创建一维数组,b[a[i].index] = i;此时离散的结果b[i]才与a[i].val值一一对应.....


#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

int n;

struct node

{

	int val, index;

}a[500010];//最初的输入 

int c[500010];//c[x]存储在区间 (x-lowbit(x)+1, x)小于等于x的个数 

bool cmp(struct node a,struct node b)

{

	return a.val<b.val;

}

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

void Update(int x)
{

	while(x<=n)

	{

		c[x]++; 

		x += lowbit(x);

	}

}

//计算的是当前区间(0, x)比x小的个数
int Sum(int x)

{

	int ans=0;

	while(x > 0)
	{

		ans += c[x];

		x -= lowbit(x);

	}

	return ans;

}

int main()

{

	while(~scanf("%d",&n) && n)
	{
		memset(c, 0, sizeof(c));

		for(int i=1;i<=n;i++)

		{

			scanf("%d", &a[i].val);

			a[i].index = i;//离散化 

		}

		sort(a+1, a+1+n, cmp);//val从小到大排序 

		long long int sum=0;//注意用long long,否则会WA 


		for(int i=1;i<=n;i++)

		{

			Update(a[i].index);

			sum += i-Sum(a[i].index); //i-Sum(x)计算的是当前比x大的个数,即逆序对数 

		}

		printf("%lld\n", sum);

	}

	return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值