小奇遐想(UPC5727)

题目描述

撷来一缕清风飘渺
方知今日书信未到
窗外三月天霁垂柳新长枝条
风中鸟啼犹带欢笑
——《清风醉梦》
小奇望着青天中的悠悠白云,开始了无限的遐想,在它的视野中,恰好有n朵高度不同的白云排成一排,他想从左到右选出四朵白云a,b,c,d,使得h_a<h_b<h_d<h_c,即看起来像是彩虹的形状!它想知道有多少种方案数。

输入

第一行包括1个整数n。
第二行包括n个整数,第i个正数表示h_i,保证这n个整数是n的一个全排列。

输出

输出一个整数表示答案。(mod 16777216)

样例输入

5
1 5 3 2 4

样例输出

0

       题目意思为给一个序列,要我们求一个四元组abdc,意思是a<b<d, d>c,也就是说要求abd是递增的然后c比d小的四元组的个数,我们可以先考虑一下用abxx的个数,abxx意思为b>a然后后面的数大于b的四元组的个数,然后我们再求一下满足abcd的四元组的个数,最后abxx-abcd就是我们要求的答案了,求abxx和abcd的个数可以用树状数组来求,abxx好求,求用b前面比他小的个数乘上后面比他大的数的个数里面选两个就可以了,abcd的个数可以用c前面ab的个数乘上后面比他大的数就可以了,也是用树状数组维护,不过维护的时候a[i]的值是ab的个数。

AC代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 2e5 + 10;
typedef long long LL;
const int M = 16777216;
long long c[maxn], a[maxn], l_min[maxn], r_max[maxn];

int lowbit(int x)
{
    return -x&x;
}

void update(int pos, long long val)
{
    for(int i = pos; i < maxn; i += lowbit(i))
    {
        c[i] += val;
    }
}

LL query(int pos)
{
    long long res = 0;
    for(int i = pos; i > 0; i -= lowbit(i))
    {
        res = (res+c[i])%M;
    }
    return res%M;
}

int main()
{
    int n;
    ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    memset(c, 0, sizeof(c));
    memset(l_min, 0, sizeof(l_min));
    memset(r_max, 0, sizeof(r_max));
    for(int i = 1; i <= n; i++)
    {
        l_min[i] = query(a[i]-1);
        update(a[i], 1);
    }
    memset(c, 0, sizeof(c));
    for(int i = n; i >= 1; i--)
    {
        r_max[i] = query(n)-query(a[i]);
        update(a[i], 1);
    }
    LL abxx = 0;
    for(int i = 1; i <= n; i++)
    {
        abxx = (abxx+l_min[i]*(r_max[i]*(r_max[i]-1)/2))%M;
    }
    LL abcd = 0;
    memset(c, 0, sizeof(c));
    for(int i = 1; i <= n; i++)
    {
        abcd = (abcd+(query(a[i]-1)*r_max[i])%M)%M;
        update(a[i], l_min[i]);
    }
    LL ans = (abxx-abcd+M)%M;
    cout << ans << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/MALONG11124/article/details/81257579
UPC