传送门:洛谷 - P1908
题目描述
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
输入描述
第一行,一个数n,表示序列中有n个数。
输出描述
第二行n个数,表示给定的序列。序列中每个数字不超过$10^9$
思路分析
逆序对也就是一个数前面有数比他大的,可以通过树桩数组求,从头开始,每次使a[i]位置的值+1,再求1~a[i]之间的和sum,i-sum就是这个数的逆序对个数,最后总和就是ans。
样例输入
6
5 4 2 6 3 1
样例输出
11
AC代码
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define ls ro<<1
#define fi first
#define se second
#define rs ro<<1|1
#define ll long long
#define pb push_back
#define vi vector<int>
#define lowbit(x) x&(-x)
#define pii pair<int,int>
#define lson ro<<1,l,mid
#define rson ro<<1|1,mid+1,r
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int INF = 0x3f3f3f3f;
const int N=5e5+10;
int n;
int b[N],a[N],bit[N];
void prepare() {
for(int i=1;i<=n;i++)
b[i]=a[i];
sort(b+1,b+n+1);
int m=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+m+1,a[i])-b;
}
}
void add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i))
bit[i]+=v;
}
int getsum(int x){
int s=0;
for(int i=x;i>=1;i-=lowbit(i))
s+=bit[i];
return s;
}
int main() {
IOS;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
prepare();
ll ans=0;
for(int i=1;i<=n;i++){
add(a[i],1);
ans+=i-getsum(a[i]);
}
cout<<ans<<endl;
return 0;
}