首页 > 代码库 > 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;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。