Poj 2299 Ultra-QuickSort 树状数组 解法

本题的树状数组稍微有点特点,就是需要所谓的离散化一下,开始听这个名称好像很神秘的,不过其实很简单。

就是把一个数组arr的值,其中的值是不连续的,变成一组连续的值,因为这样他们的顺序是不变的,所以,不影响结果。

例如:9 1 0 5 4 ->变为:5 2 1 4 3看出他们的相对位置不变的。

9和5为最大值在第一个位置,1和2为第二大的值在第二个位置,0和1在第一个位置等,看出对应顺序了吗?

对,就是这么简单的方法, 就叫做离散化。

如果你对counting sort熟悉的话,那么这样的思想理解并写出程序是毫不费力的。

当然本题如果使用归并排序会更好,不过归并太简单了。

原题:http://poj.org/problem?id=2299

我们这里使用树状数组加上上面说的离散化。

class UltraQuickSort2299
{
	const static int SIZE = 500005;
	int *reflect, *tree;
	inline int lowbit(int x)
	{
		return x & (-x);
	}

	void update(int x, int val, int len)
	{
		while (x <= len)
		{
			tree[x] += val;
			x += lowbit(x);
		}
	}

	long long query(int x)
	{
		long long ans = 0;
		while (x > 0)
		{
			ans += tree[x];
			x -= lowbit(x);
		}
		return ans;
	}

	struct Node
	{
		int val, pos;
		bool operator<(const Node a) const
		{
			return val < a.val;
		}
	};

	Node *arr;
public:
	UltraQuickSort2299():arr((Node *)malloc(sizeof(Node) * SIZE)),
		tree((int *)malloc(sizeof(int) * SIZE)),
		reflect((int *)malloc(sizeof(int) * SIZE))
	{
		int N;
		while (scanf("%d", &N) && N != 0)
		{
			for (int i = 1; i <= N; i++)
			{
				scanf("%d", &arr[i].val);
				arr[i].pos = i;
			}

			std::sort(arr+1, arr+N+1);

			for (int i = 1; i <= N; i++)
			{
				reflect[arr[i].pos] = i;//所谓的离散化,即对应到新的值,相对位置不变,下标记得变为1起点,如此倒腾的思维带counting sort的思维
			}

			std::fill(tree, tree+N+1, 0);
			long long ans = 0;
			for (int i = 1; i <= N; i++)
			{
				update(reflect[i], 1, N);
				ans += i - query(reflect[i]);
			}
			printf("%lld\n", ans);
		}
	}

	~UltraQuickSort2299()
	{
		free(tree);
		free(arr);
		free(reflect);
	}
};



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值