L i n k Link Link
D e s c r i p t i o n Description Description
I n p u t Input Input
O u t p u t Output Output
S a m p l e Sample Sample I n p u t Input Input
4
1 4 3 2
S a m p l e Sample Sample O u t p u t Output Output
3
H i n t Hint Hint
S o l u t i o n Solution Solution
树状数组求逆序对,以及求出
l
s
ls
ls(
i
i
i左边比
i
i
i小的数的个数)
l
b
lb
lb(
i
i
i左边比
i
i
i大的数的个数)
r
s
rs
rs和
r
b
rb
rb(意义和上面除了方向不一样,其余都是一样的)
然后再去掉重复的就得到答案了
C o d e Code Code
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
struct awsl{
ll x, num;
}a[100001];
ll n, size, ans, suml, sumr, sumx;
ll b[100001], c[100001];
ll sl[100001], sr[100001], bl[100001], br[100001];
bool cmp(awsl a, awsl b)
{return a.x < b.x;}
ll lowbit(ll now) {
return now & (-now);
}
void build(ll now)
{
for (; now <= n; now += lowbit(now))
c[now]++;
}//插入点
ll sum(ll now) {
sumx = 0;
for (; now; now -= lowbit(now))
sumx += c[now];
return sumx;
}
//以上是树状数组,不太懂的可以去百度一下
int main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; ++i)
{
scanf("%lld", &a[i].x);
a[i].num = i;
}
sort(a + 1, a + n + 1, cmp);
a[0].x = -1;
for (int i = 1; i <= n; ++i)
if (a[i].x != a[i - 1].x)
b[a[i].num] = ++size;
else b[a[i].num] = size;
for (int i = 1; i <= n; ++i)
{
sl[i] = sum(b[i] - 1);
bl[i] = sum(n) - sum(b[i]);
suml += bl[i];
build(b[i]);
}//求出左边的
memset(c, 0, sizeof(c));
for (int i = n; i >= 1; --i)
{
sr[i] = sum(b[i] - 1);
br[i] = sum(n) - sum(b[i]);
sumr += br[i];
build(b[i]);
}//求出右边的
ans = suml * sumr;
for (int i = 1; i <= n; ++i)
ans -= (sl[i] * sr[i]) + (bl[i] * br[i]) + (br[i] * sr[i]) + (bl[i] * sl[i]);//去重
printf("%lld", ans);
return 0;
}