POJ2299 Ultra-QuickSort 树状数组+逆序数
题意
给出一个数列,经过若干次相邻交换之后得到递增数列,求交换的总次数。
输入
有若干组数据
给出数列长度N,若N = 0则程序终止
接下来N行,代表数列组成。
输出
每组数据 输出次数
思路
计算数列逆序数的模板题
1.将数排列成升序的过程可以抽象为将逆序对数清零的过程,所以统计次数就是在计算逆序数
从前往后遍历每个数ai , 统计这个数之前比它小的数,则这个数的逆序对可得 i - 1 - 在它之前更小的数
2.可以利用树状数组 前缀和+快速更新的特性
每次计算后 将这个数的计数+1 以后的计算只需询问在它之前的更小的数的「区间和」
AC代码
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
int n;
typedef long long ll;
struct Node
{
ll val;
int pos,id;
}node[500010];
int tree[500010];
bool cmp(Node A, Node B)
{
return A.val < B.val;
}
bool cmp1(Node A,Node B)
{
return A.id < B.id;
}
#define lowbit(x) ((x) & -(x))
int sum(int x)
{
int s = 0;
while(x > 0)
{
s += tree[x];
x -= lowbit(x);
}
return s;
}
void add(int x ,int d)
{
while(x <= n)
{
tree[x] += d;
x += lowbit(x);
}
return;
}
int main()
{
while(cin >> n && n)
{
memset(tree,0,sizeof(tree));
for(int i = 1;i <= n;i ++)
{
scanf("%lld",&node[i].val);
node[i].id = i;
}
sort(node+1,node+1+n,cmp);