POJ 2299 Ultra-QuickSort 树状数组+离散化 求逆序对
原题:http://poj.org/problem?id=2299
解题思路:
树状数组的参考资料:https://www.cnblogs.com/hsd-/p/6139376.html
这里就不再赘述了。
基本思路是将一组数据从大到小插入,然后累加每次插入时计算前面比它大的元素个数(即构成逆序),这里利用离散化+树状数组,每次插入时计算插入位置n之前的n-1项和即可
输入数据同时记录下对应的数组下标,方便排序后将数据从大到小插入1。注意这里的“原数组”a[i]是不存在的,直接更新a[i]对应的树状数组即可
以9 1 0 5 4 为例,插入1的数序是 9 5 4 1 0 的对应位置
a[ ]起始为 0 0 0 0 0
插入9后 1 0 0 0 0 ans += 0
插入5后 1 0 0 1 0 ans += 1
插入4后 1 0 0 1 1 ans += 2
插入1后 1 1 0 1 1 ans += 1
插入0后 1 1 1 1 1 ans += 2
最后输出6
代码如下
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int maxn = 500010; struct T{ int d; // data int id; //index bool operator < (const T& t) const{ //使原始数据按降序排序 return d > t.d; } } b[maxn]; int n; int c[maxn]; //树状数组 int lowbit(int x) { return x&(-x); } void add(int x,int y) //update c { for(int i = x; i <=n; i+=lowbit(i)) { c[i] += y; } } int getSum(int x) // get sum of a[1..x],求a数组的前x项和 { int sum = 0; for(int i = x; i >0; i -= lowbit(i)) sum += c[i]; return sum; } int main() { long long ans; // int型会溢出 while(cin >> n && n) { memset(c,0,sizeof(c)); ans = 0; for(int i = 1; i <= n; ++i) { cin >> b[i].d; b[i].id = i; } sort(b+1,b+n+1); for(int i = 1; i <= n; ++i) { int id = b[i].id; add(id,1); //注意这里省略了插入1到a数组的过程(因为用不上),直接更新c数组(树状数组) ans += getSum(id-1); } cout << ans << endl; } return 0; }