poj 3928(树状数组)

40 篇文章 0 订阅
16 篇文章 0 订阅

Ping pong

  POJ - 3928 

#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
#include<algorithm>
#define LL long long
#define maxn 100005
#define Max(a,b) a>b?a:b
#define Min(a,b) a<b?a:b
#define lowb(x) x&-x
#define inf 0x3f3f3f3f
using namespace std;
int A[maxn];
int B[maxn];
int C[maxn];int n;
void add(int k,int lx )
{
    while(k<=lx)
    {
        C[k]+=1;
        k+=lowb(k);
    }
}
int getans(int k)
{
    int ans=0;
    while(k>0)
    {
        ans+=C[k];
        k-=lowb(k);
    }
    return ans;
}
int Find(int k,int l,int r)//找到B[i]排序后的位置以便得到比他大的数有几个比他小的数有几个。
{
    int lf=l,rg=r;
    while(lf<=rg)
    {
        int mid=(lf+rg)/2;
        if(k>A[mid]) lf=mid+1;
        if(k<A[mid]) rg=mid-1;
        if(k==A[mid]) return mid;
    }
}
int main()
{
    ios::sync_with_stdio(0);
    int t;cin>>t;
    while(t--)
    {
        memset(C,0,sizeof(C));
        cin>>n;
        int ll=0;
        for(int i=1;i<=n;i++){
            cin>>A[i];
            B[i]=A[i];
            if(B[i]>ll)ll=B[i];
        }
        LL res=0;
        sort(A+1,A+1+n);
        add(B[1],ll);
        int lf=0,rg=0;//左小右大
        int zd=0,yx=0;//左大右小
        int pp=0;
        for(int i=2;i<n;i++)
        {
            pp=Find(B[i],1,n);
            lf=getans(B[i]);
            zd=i-1-lf;
            yx=pp-1-lf;
            rg=n-pp-zd;
            res+=lf*rg+zd*yx;
           // cout<<"lf="<<lf<<"rg="<<rg<<endl;
            //cout<<"zd="<<zd<<"yx="<<yx<<endl;
            add(B[i],ll);
        }
        cout<<res<<endl;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值