poj 3928 树状数组
题目中只n个人,每个人有一个ID和一个技能值,一场比赛需要两个选手和一个裁判,只有当裁判的ID和技能值都在两个选手之间的时候才能进行一场比赛,现在问一共能组织多少场比赛。
由于排完序之后,先插入的一定是小的,所以左右两边的大于小于都能确定,用树状数组维护选手的id
Sample Input
1
3 1 2 3
Sample Output
1
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 int n,m,t; 9 const int maxn=100000; 10 __int64 c[maxn]; 11 struct node 12 { 13 int x,id; 14 }p[maxn+2]; 15 bool cmp(node a,node b) 16 { 17 return a.x<=b.x; 18 } 19 int lowbit(int i) 20 { 21 return i&(-i); 22 } 23 void add(int i,__int64 d) 24 { 25 while(i<=maxn) 26 { 27 c[i]+=d; 28 i+=lowbit(i); 29 } 30 } 31 __int64 sum(int i) 32 { 33 __int64 ret=0; 34 while(i) 35 { 36 ret+=c[i]; 37 i-=lowbit(i); 38 } 39 return ret; 40 } 41 int main() 42 { 43 int i,j,k; 44 __int64 lmin,lmax,rmin,rmax,ans=0; 45 //freopen("1.in","r",stdin); 46 scanf("%d",&t); 47 while(t--) 48 { 49 for(i=0;i<=maxn;i++) c[i]=0; 50 scanf("%d",&n); 51 for(i=1;i<=n;i++) scanf("%d",&p[i].x),p[i].id=i; 52 sort(p+1,p+1+n,cmp); 53 add(p[1].id,1); 54 for(i=2;i<n;i++) 55 { 56 lmin=sum(p[i].id-1); //计数是从1到i-1,故要多减一个1 57 lmax=p[i].id-1-lmin; 58 //printf("%I64d %I64d ",lmin,lmax); 59 rmin=sum(n)-sum(p[i].id); 60 rmax=n-p[i].id-rmin; 61 //printf("%I64d %I64d \n",rmin,rmax); 62 ans+=(lmin*rmax+rmin*lmax); add(p[i].id,1); 63 //printf("%I64d\n",ans); 64 } 65 printf("%I64d\n",ans); 66 ans=0; 67 } 68 return 0; 69 }