1144 数星星 (树状数组)

1144 数星星

该题有题解

时间限制:564MS  内存限制:65536K
提交次数:193 通过次数:43

题型: 编程题   语言: G++;GCC

 

Description

天文学家们喜欢观察星星。它们把每颗星星看成一个点,并把每颗星星左下方(即横坐标和纵坐标都不比它大)的星星颗数作为它的等级值。
现给出所有星星(星星个数为N)的坐标,计算并输出指定编号的星星的等级。

注意:不存在相同坐标的星星




输入格式

第一行为N
后N行为编号为1到N的星星的坐标(坐标用整数)
此后是M
后一行是M个星星的编号

N<=100000
M<=1000

坐标范围0<=x,y<=1000000



输出格式

要求依次输出这M个星星的等级,一行一个



 

输入样例

5
0 0
2 0
3 0
1 1
2 2
2
4 5



 

输出样例

1
3



 

作者

 admin

  要求某个星星的的左下方的星星的个数,就是求出在整组数据中x坐标和y坐标都小于等于该星星坐标的其他星星的个数。可能会想到直接套二维的树状数组,不过x,y最大为

1000000,开不下这么大的内存。 所以 把这道题"降维"先:将所有的星星先y坐标从小到大排序,如果y相同的就把x坐标较小的排前面;排完序后的数组中,对于第i个星星,扫一遍它前面的
i-1个星星,其中x坐标小于等于它的个数,就是位于它左下方的星星个数。   这里求前面i-1个元素的和可以用树状数组。用个循环从1~n更新;另开一
个大小为max_x(数据中最大的x坐标)的数组bit[]初始化为0。 因为数组已经按上面说的方法排过序了,所以所以第1个更新的元素star[1]肯定是不会有其他星星在它左下角(它的y和x坐标都是最小的了),
然后更新它updata(star[1].x),就是把bit[star[1].x] 加1后往后更新。以此类推,更新后面的元素时,他们的y坐标肯定是比前面的元素大的,所以只要计算bit[]中前i-1个所有元素的和就行了。
另外,题目要查询的是原数组中的编号,但程序中又需要对其进行排序。所以可以用结构体来存储星星的信息,里面再加一个变量pos来标记该星星的原下标是什么。 (PS:要AC这题,因为数据比较水,其
实可以在统计前面i-1个元素中x坐标比其小的个数 的这一步中可以暴力扫一遍。。。复杂度O(mn)...

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <cstdlib>
 7 #include <cctype>
 8 #include <queue>
 9 #include <stack>
10 #include <map>
11 #include <vector>
12 #include <set>
13 #include <utility>
14 #define ll long long
15 #define inf 0x3f3f3f3f
16 #define MAX_N 100000
17 #define MAX_X 1000000
18 using namespace std;
19 
20 typedef struct node
21 {
22     int x,y;
23     int p; //因为要对数组排序而询问的是原数组下标的答案,所以用个变量p来标记该元素的原下标
24 } node;
25 node star[MAX_N+5];
26 bool cmp(node a,node b) //按y大小升序来排序,y相同时把x较小的排前面
27 {
28     if(a.y!=b.y)
29         return a.y<b.y;
30     else
31         return a.x<b.x;
32 }
33 int n,m,maxn;
34 int ans[MAX_N+5]; //ans[]数组存储每个星星的等级
35 int bit[MAX_X+5]; //树状数组中的统计和的数组
36 int sum(int pos)
37 {
38     int res=0;
39     while(pos)
40     {
41         res+=bit[pos];
42         pos-=(pos&-pos);
43     }
44     return res;
45 }
46 void updata(int pos,int value)
47 {
48     while(pos<=maxn)
49     {
50         bit[pos]+=value;
51         pos+=(pos&-pos);
52     }
53 }
54 int main()
55 {
56     //freopen("input.txt","r",stdin);
57     memset(bit,0,sizeof(bit));
58     scanf("%d",&n);
59     maxn=-1;
60     for(int i=1; i<=n; i++)
61     {
62         scanf("%d%d",&star[i].x,&star[i].y);
63         star[i].x++;    //在树状下标不能有0,否则会死循环!
64         star[i].y++;   //所以然横纵坐标都+1
65         star[i].p=i;
66         if(star[i].x>maxn)
67             maxn=star[i].x;  //更新最大的x坐标
68     }
69     sort(star+1,star+n+1,cmp);//以y坐标升序来sort
70     //
71     for(int i=1; i<=n; i++)
72     {
73         ans[star[i].p]=sum(star[i].x); //计算位于其左下方的星星个数
74         updata(star[i].x,1);  //更新bit[]数组
75     }
76     //
77     scanf("%d",&m);
78     while(m--)
79     {
80         int temp;
81         scanf("%d",&temp);
82         printf("%d\n",ans[temp]);
83     }
84     return 0;
85 }

 

posted @ 2016-06-07 13:42  爱喝可乐的咖啡  阅读(947)  评论(1编辑  收藏  举报