JZOJ 1341. 失眠 题解

题目大意

给出一个长度为(n)的排列,求其中满足i<j<k且a[i]<a[k]且a[k]<a[j]的三元组(i,j,k)个数.
(nleq 100000)

思路

设满足i<j<k且a[i]<a[k]且a[k]<a[j]的三元组(i,j,k)个数为a.
满足i<j<k且a[i]<a[j]且a[j]<a[k]的三元组(i,j,k)个数为b.
满足i<j<k且a[i]<a[j]且a[i]<a[k]的三元组(i,j,k)个数为c.
显然有c=a+b

c,b都可以用树状数组轻松求出,相减就得到题目要求的a了。

Code

#include <cstdio>
#include <cstring>
#include <cstdlib>

typedef long long ll;
const int N = 2e5 + 7;

ll ans = 0, c[N], r[N];
int n, a[N];

void add(int po)
{ for (; po <= n; po += (po & (-po))) c[po]++; }
ll sum(int po)
{
	ll ret = 0;
	for (; po; po -= (po & (-po))) ret += c[po];
	return ret;
}

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", a + i);
	for (int i = n; i >= 1; i--)
	{
		r[i] = sum(n) - sum(a[i]);
		ans += r[i] * (r[i] - 1) / 2, add(a[i]);
	}
	memset(c, 0, sizeof(c));
	for (int i = 1; i <= n; i++)
		ans -= sum(a[i] - 1) * r[i], add(a[i]);
	printf("%lld
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/zjlcnblogs/p/10795697.html