Ultra-QuickSort 求最小交换次数即求逆序对数 树状数组+离散化
来源:互联网 发布:黑暗之光披风升阶数据 编辑:程序博客网 时间:2024/06/05 23:14
首先介绍一下树状数组
树状数组(binary indexed tree),是一种设计新颖的数组结构,它能够高效地获取数组中连续n个数的和。概括说,树状数组通常用于解决以下问题:数组{a}中的元素可能不断地被修改,怎样才能快速地获取连续几个数的和?
传统数组(共n个元素)的元素修改和连续元素求和的复杂度分别为O(1)和O(n)。树状数组通过将线性结构转换成伪树状结构(线性结构只能逐个扫描元素,而树状结构可以实现跳跃式扫描),使得修改和求和复杂度均为O(lgn),大大提高了整体效率。
图就不上了,举个简单的例子
设节点编号为x,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。
算这个2^k有一个快捷的办法,定义一个函数如下即可
int
lowbit(
int
x){
return
x&(x^(x–1));
}
比较常用的是
int lowbit(int x)
{
return x& (-x);
}
那么该题的题意如下
Ultra-QuickSort算法处理一个由n个不相同整数组成的序列,通过交换序列中相邻两个整数从而使得序列达到升序排列。
比如输入:
9 1 0 5 4
Ultra-QuickSort算法给出输出:
0 1 4 5 9
请算出Ultra-QuickSort算法需要进行多少次交换操作
输入以n=0结束
59105431230
60
假设输入的数组是9 1 0 5 4, 离散后的结果aa[] = {5,2,1,4,3};
在离散结果中间结果的基础上,那么其计算逆序数的过程是这么一个过程。
1,输入5, 调用upDate(5, 1),把第5位设置为1
1 2 3 4 5
0 0 0 0 1
计算1-5上比5小的数字存在么? 这里用到了树状数组的getSum(5) = 1操作,
现在用输入的下标1 - getSum(5) = 0 就可以得到对于5的逆序数为0。
2. 输入2, 调用upDate(2, 1),把第2位设置为1
1 2 3 4 5
0 1 0 0 1
计算1-2上比2小的数字存在么? 这里用到了树状数组的getSum(2) = 1操作,
现在用输入的下标2 - getSum(2) = 1 就可以得到对于2的逆序数为1。
3. 输入1, 调用upDate(1, 1),把第1位设置为1
1 2 3 4 5
1 1 0 0 1
计算1-1上比1小的数字存在么? 这里用到了树状数组的getSum(1) = 1操作,
现在用输入的下标 3 - getSum(1) = 2 就可以得到对于1的逆序数为2。
4. 输入4, 调用upDate(4, 1),把第5位设置为1
1 2 3 4 5
1 1 0 1 1
计算1-4上比4小的数字存在么? 这里用到了树状数组的getSum(4) = 3操作,
现在用输入的下标4 - getSum(4) = 1 就可以得到对于4的逆序数为1。
5. 输入3, 调用upDate(3, 1),把第3位设置为1
1 2 3 4 5
1 1 1 1 1
计算1-3上比3小的数字存在么? 这里用到了树状数组的getSum(3) = 3操作,
现在用输入的下标5 - getSum(3) = 2 就可以得到对于3的逆序数为2。
6. 0+1+2+1+2 = 6 这就是最后的逆序数
那么最后看一下代码//
#include "stdafx.h"
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int n;
struct node
{
int val, order;
bool operator < (const node & x)
{
return val < x.val;
}
}c[500010];
int a[500010];
int t[500010];
int lowbit(int x)
{
return x&(-x);
}
void add_t(int x)
{
while (x <= n)
{
t[x] += 1;
x += lowbit(x);
}
}
int get_sum(int x)
{
int res=0;
while (x > 0)
{
res += t[x];
x -= lowbit(x);
}
return res;
}
int main()
{
long res;
while (1)
{
memset(t, 0, sizeof(t));
//scanf("%d", &n);
cin >> n;
if (n == 0) break;
for (int i = 1; i <= n; i++)
{
cin >> c[i].val; //scanf("%d", &c[i].val);
c[i].order = i;
}
sort(c + 1, c+1+n);
/*
debug
for (int i = 1; i <= n; i++)
cout << " " << c[i].val;
cout << endl;
debug
*/
for (int i = 1; i <= n; i++)
a[c[i].order] = i;
/*
for (int i = 1; i <= n; i++)
cout << " " << a[i];
cout << endl;
*/
res = 0;
for (int i = 1; i <= n; i++)
{
add_t(a[i]);
res += i - get_sum(a[i]);
}
cout << res << endl;
}
return 0;
}
- Ultra-QuickSort 求最小交换次数即求逆序对数 树状数组+离散化
- POJ-2299 Ultra-QuickSort (树状数组 离散 求逆序对数)
- poj2299 Ultra-QuickSort&&NYOJ117 求逆序数 (树状数组求逆序对数+离散化)+(归并排序)
- (POJ 2299)Ultra-QuickSort 树状数组求逆序对数 + 离散化
- Ultra-QuickSort(离散化+树状数组求逆序数)
- Ultra-QuickSort(树状数组+离散化+求逆序)
- 离散化+树状数组 求逆序对数
- 【树状数组】poj2299 Ultra-QuickSort(离散化+树状数组求逆序数)
- UVA 10810 - Ultra-QuickSort(树状数组+离散化求逆序对)
- POJ 2299 Ultra-QuickSort(树状数组+离散化 或 归并排序求逆序)
- POJ2299 Ultra-QuickSort——树状数组求逆序数+离散化
- poj2299 Ultra-QuickSort(树状数组求逆序数,离散化)
- POJ 2299 Ultra-QuickSort (树状数组求逆序数+离散化)
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- 树状数组 离散化 求逆序数POJ 2299Ultra-QuickSort解题报告
- POJ 2299 Ultra-QuickSort(树状数组+离散化—求逆序数)
- JAVA学习中的心得和小程序
- 小白学分布式程序开发3-分布式系统的数据一致性问题
- SpringBoot学习:使用spring-boot-devtools进行热部署
- equals 与 ==
- 后端api之路——初窥门径
- Ultra-QuickSort 求最小交换次数即求逆序对数 树状数组+离散化
- 深度学习(一)——MP神经元模型, BP算法, 神经元激活函数, Dropout
- BC系列教程下载地址
- ClassNotFoundException: org.apache.jsp.index_jsp错误解决方案
- poj2115 扩展欧几里德算法小结
- pwn工具箱之unsorted bin attack
- /etc/ld.so.conf文件
- MySQL主从复制与主主复制
- 提高win7开机启动速度