题目:求逆序数
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;
}