考点
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 3e4 + 50; int n, tot, dis[maxn], a[maxn], bit[maxn]; int l[maxn], r[maxn];
int lowbit(int x) { return x & -x; }
void add(int x, int v) { while (x <= n) { bit[x] += v; x += lowbit(x); } }
int ask(int x) { int s = 0; while (x > 0) { s += bit[x]; x -= lowbit(x); } return s; }
int main() { cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i], dis[i] = a[i]; sort(dis + 1, dis + 1 + n); tot = unique(dis + 1, dis + 1 + n) - 1 - dis; for (int i = 1; i <= n; ++i) { int x = lower_bound(dis + 1, dis + 1 + tot, a[i]) - dis; a[i] = x; } for (int i = 1; i <= n; ++i) { if (a[i] - 1) l[i] = ask(a[i] - 1); add(a[i], 1); } memset(bit, 0, sizeof(bit)); for (int i = n; i >= 1; --i) { if (a[i] + 1 <= n) r[i] = ask(tot) - ask(a[i]); add(a[i], 1); } ll ans = 0; for (int i = 1; i <= n; ++i) ans += (ll)l[i] * r[i]; cout << ans << endl; return 0; }
|
思路
假设离散化后,1
是最小数字的排名,n
是最大数字的排名,把原来的数字用排名替代。
遍历时使用权值树状数组记录每个排名的出现次数,
从左向右遍历,对于每个当前排名ai,比它小的排名区间为1到ai
- 1,那么比它小的个数就等于ask(a[i] - 1)
结果保存到l[i]
。
从右往左遍历,对于每个当前排名ai,比它大的排名区间为ai
+ 1 到
n
,那么比它大的个数就等于ask(n) - ask(a[i])
结果保存到r[i]
。
根据乘法原理,答案就等于l[i] * r[i]
之和