本题的树状数组稍微有点特点,就是需要所谓的离散化一下,开始听这个名称好像很神秘的,不过其实很简单。
就是把一个数组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);
}
};