JZOJ 1341. 失眠 题解

题目大意

给出一个长度为\(n\)的排列,求其中满足i<j<k且a[i]<a[k]且a[k]<a[j]的三元组(i,j,k)个数.
\(n\leq 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\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zjlcnblogs/p/10795697.html
今日推荐