poj2481_树状数组

题意:FJ有n头牛(编号为1~n),每一头牛都有一个测验值[S, E],如果对于牛i和牛j来说,它们的测验值满足下面的条件则证明牛i比牛j强壮:Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj。现在已知每一头牛的测验值,要求输出每头牛有几头牛比其强壮。

分析:将[s,e]看成是而为坐标轴的横纵坐标,画出各个点,我们发现答案就是每个点左上的点的个数。将e降序,再将s升序,就可以转化成一维。

例如:

1 2
1 2
0 3
3 4,排序后为

3 4
0 3
1 2
1 2,这样就转化成横坐标前面小于它的个数。

这个题离散到大于等于1的范围内即可。

难点是,对重复坐标的处理,之前做过的题都是不会有重复的。

重复的点直接拷贝答案就行,不用getsum().

代码:

View Code
 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <memory.h>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxnum=100005;
 7 struct node
 8 {
 9     int l,r;
10     int pos;
11 }array[maxnum];
12 int tree[maxnum];
13 int ans[maxnum];
14 int n;
15 
16 bool cmp(struct node a,struct node b)
17 {
18     if(a.r==b.r)
19         return a.l<b.l;
20     return a.r>b.r;
21 }
22 
23 void update(int index,int add)
24 {
25     while(index<=maxnum)  //因为没有紧凑化,所以<=maxn;如果紧凑化到n个散列号的话,<=n就可以了
26     {
27         tree[index]+=add;
28         index+=(-index)&index;
29     }
30 }
31 
32 int getsum(int index)
33 {
34     int sum=0;
35     while(index>0)
36     {
37         sum+=tree[index];
38         index-=(-index)&index;
39     }
40     return sum;
41 }
42 
43 int main()
44 {
45     int i;
46     while(scanf("%d",&n) && n!=0)
47     {
48         for(i=0;i<n;i++)
49         {
50             scanf("%d%d",&array[i].l,&array[i].r);
51             array[i].pos=i;
52         }
53         sort(array,array+n,cmp);
54         memset(tree,0,sizeof(tree));
55         int cnt=0;
56         for(i=0;i<n;i++)
57         {
58             if(i!=0 && array[i].l==array[i-1].l && array[i].r==array[i-1].r)
59             {
60                 ans[array[i].pos]=ans[array[i-1].pos]; //注意
61                 cnt++;
62             }
63 //            else  这样为什么不行?????求助!!!!
64 //            {
65 //                update(array[i].l+1,1);
66 //                ans[array[i].pos]=getsum(array[i].l+1)-1+cnt;
67 //            }
68             else
69                 ans[array[i].pos]=getsum(array[i].l+1);
70             update(array[i].l+1,1);
71         }
72         for(i=0;i<n-1;i++)
73             printf("%d ",ans[i]);
74         printf("%d\n",ans[i]);
75     }
76     return 0;
77 }
78 
79 /*
80 4
81 1 2
82 1 2
83 0 3
84 3 4
85 */

 

 

posted @ 2012-08-19 11:11  pushing my way  阅读(203)  评论(0编辑  收藏  举报