AcWing 241. 楼兰图腾
原题链接
简单
作者:
NextAutumn
,
2025-01-12 16:34:16
,
所有人可见
,
阅读 3
//经典树状数组求逆序对数量
//求出 左边比当前数大的数的和,求出右边比当前数大的和,乘法原理就是V,^同理
#include<bits/stdc++.h>
#define lowbit(x) x & (-x)
using namespace std;
typedef long long ll;
const int N = 2e5 + 10, inf = 0x3f3f3f3f;
int n;
int a[N], tr[N];
int bigger[N], lower[N];
void add(int id, int x)
{
for(int i = id; i <= n; i += lowbit(i)) tr[i] += x;
}
ll qurry(int l, int r)//注意,查询区间是(l,r]
{
int tolr = 0, toll = 0;
for(int i = r; i; i -= lowbit(i)) tolr += tr[i];
for(int i = l; i; i -= lowbit(i)) toll += tr[i];
return tolr - toll;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++)//左往右
{
int y = a[i];
bigger[i] = qurry(y, n);//比当前数大的数字的个数,就是树状数组中[y + 1, n]中的数字和
lower[i] = qurry(0, y - 1);//比当前数字小的数的个数,就是树状数组中[1, y - 1]中的数字和
add(y, 1);
}
memset(tr, 0, sizeof tr);
ll res1 = 0, res2 = 0;
for(int i = n; i; i --)//右往左
{
int y = a[i];
res1 += bigger[i] * (ll)qurry(y, n);
res2 += lower[i] * (ll)qurry(0, y - 1);
add(y, 1);
}
cout << res1 << ' ' << res2 << '\n';
return 0;
}