首页 > 代码库 > hdu 2492 Ping pong 线段树

hdu 2492 Ping pong 线段树

给定一个序列,求出一共有多少个三元组(ai,aj,ak),使得i<j<k,ai<aj<ak。

固定中间值,查找前面比他大的有多少,比他小的有多少,查找后面比他大的有多少,比他小的有多少。

#include <stdio.h>#include <string.h>#define maxn 100200#define N 20100int sum[maxn*4];int lmax[N],lmin[N],rmax[N],rmin[N];int ans[N];void pushup(int o){    sum[o]=sum[o*2]+sum[o*2+1];}void build(int l,int r,int o){    if(l==r)    {        sum[o]=0;        return ;    }    else    {        int m=(l+r)/2;        build(l,m,o*2);        build(m+1,r,o*2+1);        pushup(o);    }}void update(int p,int l,int r,int o){    if(l==r)    {        sum[o]++;        return ;    }    int m=(l+r)/2;    if(p<=m) update(p,l,m,o*2);    else update(p,m+1,r,o*2+1);    pushup(o);}int query(int L,int R,int l,int r,int o){    if(L<=l && r<=R) return sum[o];    int m=(l+r)/2,tot=0;    if(L<=m) tot+=query(L,R, l,m,o*2);    if(R>m) tot+=query(L,R, m+1,r,o*2+1);    return tot;}int main(){    int cas;    scanf("%d",&cas);    int n;    int i,j;    while(cas--)    {        scanf("%d",&n);        __int64 xx=0;        for(i=1;i<=n;i++)            scanf("%d",&ans[i]);        build(1,maxn,1);        for(i=1;i<=n;i++)        {            update(ans[i],1,maxn,1);            lmax[i]=query(ans[i], maxn, 1, maxn, 1)-1;            lmin[i]=query(1, ans[i], 1, maxn, 1)-1;        }        build(1,maxn,1);        for(i=n;i>0;i--)        {            update(ans[i],1,maxn,1);            rmax[i]=query(ans[i],maxn,1,maxn,1)-1;            rmin[i]=query(1,ans[i],1,maxn,1)-1;        }        for(i=2;i<n;i++)            xx=xx+lmin[i]*rmax[i]+rmin[i]*lmax[i];        printf("%I64d\n",xx);    }    return 0;}