AcWing 241. 楼兰图腾
原题链接
简单
作者:
QQQQJ
,
2024-10-04 11:58:44
,
所有人可见
,
阅读 2
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
// #define int long long
typedef long long ll;
int n, m;
int a[N], tr[N];
int gre[N], lower[N];//在i这个位置左边,比a[i]小的数的个数
int lowbit(int x) {
return x & -x;
}
void add(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
tr[i] += k;
}
}
ll ask(int x) {
ll res = 0;
for (int i = x; i >= 1; i -= lowbit(i)) { //注意这里是减
res += tr[i];
}
return res;
}
signed main() {
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) {
int y = a[i];
//因为查修的是i这个位置的左边有多少比它大/小的数。
//因此需要先查后插,如果插多了,ask返回的就是全局上右多少比它大/小的数。
//从左往右一个一个插,插入之前,已经存在的。才是左边的符合要求的点的 个数!
//ask其实也是全局,只不过右边部分还没插入,全是0
gre[i] = ask(n) - ask(y);
lower[i] = ask(y - 1);
add(y, 1);
}
//插完之后,全局ask减掉左边ask就是右边比当前a[i]大的个数
//插完之后,不能再用ask查询左边,这个时候已经是全局查询,我们要用之前保留下来的g和l数组计算
ll ansA = 0, ansV = 0;
for (int i = 1; i <= n; i ++ ) {
int y = a[i];
ansV += gre[i] * ( (ask(n) - ask(y) ) - gre[i] );
ansA += lower[i] * (ask(y - 1) - lower[i]);
}
cout << ansV << " " << ansA << endl;
}