解题思路
每个小朋友需要交换的次数必然是左边比他大的 + 右边比他小的
用 权值BIT 维护前缀后缀再单独计算等差即可
主席树应该也是可以解决的
/*
Zeolim - An AC a day keeps the bug away
*/
//#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <sstream>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef long double ld;
const int INF = 0x3f3f3f3f;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const int MAXN = 1e7 + 10;
ll arr[MAXN] = {0};
ll cnt[MAXN] = {0};
ll c[MAXN] = {0};
ll lobit(ll x)
{
return x & -x;
}
void add(ll x, ll n)
{
for(; x <= n; x += lobit(x))
++c[x];
}
ll ask(ll x)
{
ll ret = 0;
for( ; x; x -= lobit(x))
ret += c[x];
return ret;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
ll n, ln = 0;
cin >> n;
for(int i = 1; i <= n; ++i)
{
cin >> arr[i];
++arr[i];
ln = max(ln, arr[i]);
}
for(int i = n; i >= 1; --i)
{
int pos = arr[i];
cnt[i] += ask(pos - 1);
add(pos, ln);
}
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; ++i)
{
int pos = arr[i];
cnt[i] += (ask(ln) - ask(pos));
add(pos, ln);
}
ll ans = 0;
for(int i = 1; i <= n; ++i)
{
//cout << cnt[i] << '
';
if(cnt[i])
{
ans += ( (1 + cnt[i]) * (cnt[i]) / 2 ) ;
}
}
cout << ans << '
';
return 0;
}