1144 数星星 (树状数组)
Posted 谜原
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于1144 数星星 (树状数组)的主要内容,如果未能解决你的问题,请参考以下文章