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 }

 

posted @ 2015-02-09 16:36  miao_a_miao  阅读(141)  评论(0编辑  收藏  举报