题目:求逆序数
https://vjudge.net/problem/POJ-2299
思路:
才学的树状数组准备写题,谁知道第一题就被暴打。
树状数组求逆序数,没输入一个数在之前输入过的数中找比当前数大的数。
用树状数组实现即,维护一段数组,每次输入一个数用树状数组的特性,找到之前比它小的数的个数。
用已经输入过的数减掉,就是比当前数大的数。
同时此题需要用到离散化的思想,看了多个博客后明白了。
就是把输入N个的大小差距特别大的数转化为从(1-N)来表示,同时不改变原输入的大小顺序,
可以减少开的树状数组的大小。
代码:
//#include <bits/stdc++.h> #include <iostream> #include <memory.h> #include <algorithm> using namespace std; const int MAXN = 500000+10; int a[MAXN]; int c[MAXN]; int n; struct Node { int v; int w; bool operator < (const Node & that) const{ return this->v < that.v; } }; Node node[MAXN]; int lowbit(int x) { return x&-x; } void update(int pos,int v) { while (pos <= n) { c[pos] += v; pos += lowbit(pos); } } int getsum(int pos) { int sum = 0; while (pos > 0) { sum += c[pos]; pos -= lowbit(pos); } return sum; } int main() { while (cin>>n&&n) { for (int i = 1;i<=n;i++) { cin>>node[i].v; node[i].w = i; } sort(node+1,node+n+1); //memset(a,0, sizeof(a)); memset(c,0, sizeof(c)); for (int i = 1;i<=n;i++) a[node[i].w] = i; long long ans = 0; for (int i = 1;i <= n;i++) { update(a[i],1); ans += i-getsum(a[i]); } cout<<ans<<endl; } return 0; } /* 5 9 1 0 5 4 */
考虑到数组内可能由重复数字,将离散化代码更新
int pos = 1; a[node[1].w] = 1; for (int i = 2;i<=n;i++) { if (node[i].v == node[i-1].v)//当值相同时,对应的位置为首个位置 a[node[i].w] = pos; else a[node[i].w] = ++pos; }