题意
在一个序列中,存在三个数为升序摆放或降序摆放,则这三个数可以视作能够举行比赛。问比赛的种数。
ps.升序或降序表示两个运动员之间的人中有人可以充当裁判,同时两个运动员愿意去裁判家中比赛。
思路
若 a 1 a_1 a1 到 a i − 1 a_{i-1} ai−1 有 b i b_i bi 个数比 a i a_i ai 小,那么就有 i − 1 − b i i-1-b_i i−1−bi 个数比 a i a_i ai 大。所以我们可以记录 a i a_i ai 左边比 a i a_i ai 小的数与 a i a_i ai 右边比 a i a_i ai 小的数。
建立两个树状数组,边遍历序列边更新数组,树状数组的第 i i i 位记录当前比 i i i 小的数的个数。 l l l 数组正序遍历更新,代表 a i a_i ai 左边比 a i a_i ai 小的数。同理, r r r 数组倒序为右边比 a i a_i ai 小的数。
答案即为 ∑ 1 n [ l i × ( n − i − r i ) + ( i − 1 − l i ) × r i ] \sum_{1}^{n} [l_i \times (n-i-r_i)+(i-1-l_i) \times r_i] ∑1n[li×(n−i−ri)+(i−1−li)×ri]
Accepted code
/*
* @Autor: CofDoria
* @Date: 2021-03-06 19:14:39
* @LastEditTime: 2021-03-08 16:55:47
*/
#include <bits/stdc++.h>
using namespace std;
#define db double
#define ll long long
#define lowbit(x) (x & -x)
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define debug(a) cout << '#' << a << '#' << '\n'
#define rep(l, a, b) for (register ll l = a; l < b; ++l)
#define per(l, a, b) for (register ll l = a; l >= b; --l)
#define _ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define _forit(i, c) \
for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); ++i)
bool fi = true;
const unsigned long long MOD = 1e9 + 7;
inline ll gcd(ll a, ll b) {
return (b == 0 ? a : gcd(b, a % b)); }
ll t, n, a[100005];
ll l[100005], r[100005];
ll ansl[100005], ansr[100005];
ll ans;
// vector<int> q;
void addl(int x) {
while (x <= 100000) ++l[x], x += lowbit(x);
}
ll suml(int x) {
ll cnt = 0;
while (x) cnt += l[x], x -= lowbit(x);
return cnt;
}
void addr(int x) {
while (x <= 100000) ++r[x], x += lowbit(x);
}
ll sumr(int x) {
ll cnt = 0;
while (x) cnt += r[x], x -= lowbit(x);
return cnt;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
_ios;
cin >> t;
while (t--) {
ans = 0;
s(l, 0);
s(r, 0);
cin >> n;
rep(i, 0, n) {
cin >> a[i];
ansl[i] = suml(a[i]);
addl(a[i]);
}
per(i, n - 1, 0) {
ansr[i] = sumr(a[i]);
addr(a[i]);
ans += ansr[i] * (i - ansl[i]) + ansl[i] * (n - 1 - i - ansr[i]);
}
cout << ans << '\n';
}
// fclose(stdin);
// fclose(stdout);
return 0;
}