逆序对
题目
输入
第一行为整数 n n n ,表示序列长度
第二行 n n n 个整数,表示给定的序列
输出
输出逆序对总数
输入样例
4
3 2 3 2
输出样例
3
解题思路
我们这题先从左到右枚举,来计算 a i a_i ai的逆序对,但是这样时间复杂度为 O ( N 2 ) O(N^2) O(N2)
显然不太优,那么我们就可以考虑用树状数组来进行优化,我们依旧先从左到右枚举
每次在树状数组中下标 a i a_i ai的位置加一,查询树状数组中下标大于 a i a_i ai的区间的元素个数,然后进行累计答案即可
程序如下
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n, tot;
long long ans, a[500006], p[500006], c[500006];
void update(int x,int y)
{
for(; x <= tot; x += x & -x) c[x] += y;
}
long long query(int x)
{
long long anss = 0;
for(; x; x -= x & -x) anss += c[x];
return anss;
}
int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; ++i)
{
scanf("%lld",&a[i]);
p[i] = a[i];
}
sort(p + 1, p + 1 + n);
tot = unique(p + 1, p + 1 + n) - 1 - p;
for(int i = 1; i <= n; ++i)
a[i] = lower_bound(p + 1, p + 1 + tot, a[i]) - p;
for(int i = 1; i <= n; ++i)
{
update(a[i], 1);
ans += query(tot) - query(a[i]);
}
printf("%lld",ans);
return 0;
}