如果树状数组维护的是a数组的值,那么 sum[i] 表示在 a 数列1~i中的元素的和
查询(l,r)中元素的和就为 sum(r)-sum(l)
逆序对的定义: i < j && a[i] > a[j]
例题中的逆序对: pre[i]为1~i中a[i]的个数; nex[i]为i~n中a[i]的个数
这时候的逆序对就是,i < j && pre[i] > nex[j]
注意求法,很神奇
#include<iostream>
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
const int maxn = 1000017;
int n;
int a[maxn], c[maxn];
int nex[maxn], pre[maxn];
ll res;
map <int, int> freq;
int Lowbit(int x) //2^k
{
return x&(-x);
}
void update(int i, int x)//i点增量为x
{
while (i <= n)
{
c[i] += x;
i += Lowbit(i);
}
}
int sum(int x)//区间求和 [1,x]
{
int sum = 0;
while (x > 0)
{
sum += c[x];
x -= Lowbit(x);
}
return sum;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
//pre[i]为1~i中a[i]的个数
//nex[i]为i~n中a[i]的个数
for (int i = 0; i < n; i++) {
pre[i] = ++freq[a[i]];
}
freq.clear();
for (int i = n - 1; i > 0; i--) {
nex[i] = ++freq[a[i]];
}
for (int i = 0; i < n; i++) {
//这两步可以说是很精妙了,首先当插入i之后,我们query的时候i的坐标已经+1了
//这时候我们查询序列中有多少个数比nex[i]大其实就是查询数组中有多少个数比nex[i]大
//一个数组的话就是update谁,就查询谁
res += i - sum(nex[i]);
update(pre[i], 1);
}
cout << res << endl;
return 0;
}