BIT LA 4329 Ping pong

时间:2024-10-11 00:06:56

题目传送门

题意:训练指南P197

分析:枚举裁判的位置,用树状数组来得知前面比它小的和大的以及后面比它小的和大的,然后O (n)累加小 * 大 + 大 * 小 就可以了

#include <bits/stdc++.h>
using namespace std; typedef long long ll;
const int N = 1e5 + 5;
const int M = 2e4 + 5;
struct BIT {
int c[N], sz;
void init(int n) {
memset (c, 0, sizeof (c));
sz = n;
}
void updata(int i, int x) {
while (i <= sz) {
c[i] += x; i += i & -i;
}
}
int query(int i) {
int ret = 0;
while (i) {
ret += c[i]; i -= i & -i;
}
return ret;
}
}bit;
int a[M], small[M][2], large[M][2]; int main(void) {
int T; scanf ("%d", &T);
while (T--) {
bit.init (100000);
int n; scanf ("%d", &n);
for (int i=1; i<=n; ++i) {
scanf ("%d", &a[i]);
small[i][0] = bit.query (a[i] - 1);
large[i][0] = i - 1 - small[i][0];
bit.updata (a[i], 1);
}
for (int i=1; i<=n; ++i) {
small[i][1] = bit.query (a[i] - 1) - small[i][0];
large[i][1] = n - i - small[i][1];
}
ll ans = 0;
for (int i=1; i<=n; ++i) {
ans += 1ll * small[i][0] * large[i][1];
ans += 1ll * large[i][0] * small[i][1];
}
printf ("%lld\n", ans);
} return 0;
}