hdu 5792 思维+树状数组

Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1 ≤ a< b ≤n,1 ≤ c < d ≤ n,Aa < Ab,Ac > Ad a≠b≠c≠d,1≤ a < b ≤n,1≤ c < d ≤n,Aa < Ab,Ac > Ad.
Input
The input consists of multiple test cases.
Each test case begin with an integer n in a single line.

The next line contains n integers A1,A2⋯AnA1,A2⋯An.
1≤n≤500001≤n≤50000
0≤Ai≤1e90≤Ai≤1e9
Output
For each test case,output a line contains an integer.
Sample Input
4
2 4 1 3
4
1 2 3 4
Sample Output
1
0

首先确定d,把前面所有比它大的作为c,a,b 就是整个序列里面所有位置前面有多少比它小的总数,然后再排除掉 a=c||b==c||a==d||b==d 的情况就好了。

纪录四个东西 qd (1,i-1) 比a[i] 大的数
qx(1,i-1) 比a[i]小的数
hd(i+1,n) 比a[i]大的数
hx(i+1,n) 比a[i]小的数

a=c 必然 b!=d因为一个要大一个要小
其他同理

#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
int a[N],b[N];
int id[N];
int qx[N],qd[N],hx[N],hd[N];
int c[N];
typedef long long ll;
#define lowbit(x) (x)&(-x)
void update(int x)
{
    while(x<=N-5)
    {
        c[x]++;
        x+=lowbit(x);
    }
}

int sum(int x)
{
    int res=0;
    while(x>0)
    {
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}

int main(){
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+n+1);
        for(int i=1;i<=n;i++){
            id[i]=lower_bound(b+1,b+n+1,a[i])-b;
        }
        ll ss=0;
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
        {
            update(id[i]);
            qx[i]=sum(id[i]-1);
            qd[i]=sum(n)-sum(id[i]);
            ss+=qx[i];
        }
        memset(c,0,sizeof(c));
        for(int i=n;i>0;i--)
        {
            update(id[i]);
            hx[i]=sum(id[i]-1);
            hd[i]=sum(n)-sum(id[i]);
        }
        ll res=0;
        for(int i=1;i<=n;i++)
        {
            res+=1ll*ss*qd[i];
        }
        for(int i=1;i<=n;i++)
        {
            res-=1ll*hd[i]*hx[i];
            res-=1ll*hd[i]*qd[i];
            res-=1ll*qx[i]*hx[i];
            res-=1ll*qx[i]*qd[i];
        }
        printf("%lld\n",res );
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值