AcWing241.楼兰图腾(树状数组)
作者:
冰冷酒
,
2022-02-20 12:54:33
,
所有人可见
,
阅读 180
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 200010;
int a[N], tr[N];
LL Greater[N], lower[N];
int n;
int lowbit(int x) // 经典lowbit
{
return x & -x;
}
void add(int x, int k) // 在x的位置加1,会影响到包含x的树状数组,所以更改x,就要讲所有连带着的树状数组修改
{
for (int i = x; i <= n; i += lowbit(i))
tr[i] += k;
}
int sum(int x) // 区间求和就要取到所有覆盖的树状数组,做到不重不漏
{
LL res = 0;
for (int i = x; i; i -= lowbit(i))
res += tr[i];
return res;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
for (int i = 1; i <= n; i ++) // 先从前往后扫一遍,统计所有大于y和小于y的个数
{
int y = a[i];
Greater[i] = sum(n) - sum(y);
lower[i] = sum(y - 1);
add(y, 1); // 记得把这个点加到树状数组中
}
LL res1 = 0, res2 = 0;
memset(tr, 0, sizeof(tr)); // 在存完Greater和lower后将树状数组清空,以便继续统计
for (int i = n; i >= 1; i --)
{
int y = a[i];
res1 += Greater[i] * (sum(n) - sum(y)); // 利用乘法原理,求出总数
res2 += lower[i] * sum(y - 1); // 同上
add(y, 1); // 记得把这个点加到树状数组中
}
cout << res1 << ' ' << res2 << endl;
return 0;
}