hdu 5792 2016多校5

题意:给出一列数,求多少个四元组(a!=b!=c!=d,1<=a<b<=n&&1<=c<d<=n&&Aa<Ab&&Ac>Ad)

题解:统计每一个数左侧有多少个大于它,多少个小于它,右侧有多少个大于它,多少个小于它。然后就是加加减减。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<algorithm>
#include<vector>
using namespace std;

class Bit{
private:
    int n;
    vector<int> d;
public:
    void init(int n){
        this->n = n+2;
        d = vector<int> (n+2,0);
    }
    int sum(int p){
        int ret = 0;
        while(p>0){
            ret+=d[p];
            p-=lowbit(p);
        }
        return ret;
    }
    int lowbit(int x){
        return x&-x;
    }
    int sum(int l,int r){
        if(l>r) return 0;
        return sum(r)-sum(l-1);
    }
    void add(int p,int x){
        while(p<n){
            d[p]+=x;
            p+=lowbit(p);
        }
    }
};
#define N 50100
typedef long long LL;
LL ls[N],lb[N],rs[N],rb[N];
int a[N];

int main(){
    int n;
    while(scanf(" %d",&n)==1){

        vector<int> ta;
        for(int i=1;i<=n;i++){
            scanf(" %d",&a[i]);
            ta.push_back(a[i]);
        }
        sort(ta.begin(),ta.end());
        ta.resize(unique(ta.begin(),ta.end())-ta.begin());
        for(int i=1;i<=n;i++){
            a[i] = lower_bound(ta.begin(),ta.end(),a[i])-ta.begin()+1;
        }

        Bit bit;
        bit.init(n);
        for(int i=1;i<=n;i++){
            ls[i] = bit.sum(1,a[i]-1);
            lb[i] = bit.sum(a[i]+1,n);
            bit.add(a[i],1);
        }

        bit.init(n);
        for(int i=n;i>=1;i--){
            rs[i] = bit.sum(1,a[i]-1);
            rb[i] = bit.sum(a[i]+1,n);
            bit.add(a[i],1);
        }

        LL l1 = 0,l2=0;
        for(int i=1;i<=n;i++){
            l1+=rs[i];
            l2+=rb[i];
        }
        LL ret = l1*l2;
        for(int i=1;i<=n;i++){
            ret-=rb[i]*rs[i];
            ret-=ls[i]*lb[i];

            ret-=lb[i]*rb[i];
            ret-=ls[i]*rs[i];
        }
        printf("%I64d\n",ret);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值