首页 > 其他 > 详细

JZOJ 1341. 失眠 题解

时间:2019-04-30 14:44:33      阅读:142      评论:0      收藏:0      [点我收藏+]

题目大意

给出一个长度为\(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;
}

JZOJ 1341. 失眠 题解

原文:https://www.cnblogs.com/zjlcnblogs/p/10795697.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!