1、题目链接
http://poj.org/problem?id=2299
2、分析:
求解逆序对问题可以用树状数组,自己画了两次图,顺带看了一些博客,大致明白了如何利用这个公式: i - getsum(b[i]) , 不过还得再搞一搞
题目的数据大小范围是在0 ≤ a[i] ≤ 999,999,999,这个为什么要离散化,是因为要将其存到树状数组中会占用太大的空间,所以用求出其一个相对大小,就拿给定的数据例子来看
9 1 0 5 4 相对大小就是 5 2 1 4 3,也就是9是第5大的数,以此类推就好
推荐看看这几篇博客写的分析,分析的比较不错。个人感觉不要只照着代码敲,不理解很难学会,其实当看懂分析后代码就很简单地k.o了
转:
(1)、http://blog.youkuaiyun.com/SeasonJoe/article/details/50193789?locationNum=15&fps=1
(2)、http://blog.youkuaiyun.com/guhaiteng/article/details/52138756
3、代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<stack> #include<queue> #include<string.h> typedef long long ll; using namespace std; const int maxn = 500010; ll n; ll b[maxn]; ll c[maxn]; ll Lowbit(ll x) { return x&(-x); } void Update(ll pos, ll num) { while(pos <= n) { c[pos] += num; pos += Lowbit(pos); } } ll Getsum(ll pos) { ll sum = 0; while(pos > 0) { sum += c[pos]; pos -= Lowbit(pos); } return sum; } struct Node { ll value; ll index; }a[maxn]; bool cmp(Node n1, Node n2) { return n1.value < n2.value; } int main() { while(~scanf("%lld",&n)) { memset(c,0,sizeof(c)); if(n == 0) break; for(ll i = 1; i <= n; i++) { scanf("%lld",&a[i].value); a[i].index = i; } sort(a,a+n+1,cmp); for(ll i = 1; i <= n; i++) { b[a[i].index] = i; } ll ans = 0; for(ll i = 1; i <= n; i++) { Update(b[i],1); ans += i - Getsum(b[i]); } printf("%lld\n",ans); } return 0; }