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 }
时间: 2024-10-14 03:37:26

1144 数星星 (树状数组)的相关文章

树状数组求逆序对:POJ 2299、3067

前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换相邻的两数使它有序,要你求出交换的次数.实质上就是求逆序对,网上有很多人说它的原理是冒泡排序,可以用归并排序来求出,但我一时间想不出它是如何和归并排序搭上边的(当初排序没学好啊~),只好用刚学过的树状数组来解决了.在POJ 1990中学到了如何在实际中应用上树状数组,没错,就是用个特殊的数组来记录即

hdu 1541 Stars 树状数组水题

Stars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5210    Accepted Submission(s): 2053 Problem Description Astronomers often examine star maps where stars are represented by points on a pla

HDU 5775 树状数组

Bubble Sort Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 853    Accepted Submission(s): 504 Problem Description P is a permutation of the integers from 1 to N(index starting from 1).Here is t

【bzoj2384】[Ceoi2011]Match 特殊匹配条件的KMP+树状数组

题目描述 给出两个长度分别为n.m的序列A.B,求出B的所有长度为n的连续子序列(子串),满足:序列中第i小的数在序列的Ai位置. 输入 第一行包含两个整数n, m (2≤n≤m≤1000000). 第二行包含n个整数si,构成1,2,…,n的排列,1≤si≤n且si≠sj. 第三行包含m个整数hi,表示建筑的高度(1≤hi≤109,1≤i≤m),所有的hi均不相同. 每一行的整数之间用单个空格隔开. 输出 第一行包含1个整数k ,表示匹配的序列数目.第二行包含k个整数,分别为在正确匹配的每个序

hdu4777 Rabbit Kingdom 树状数组+区间操作+素数打表

题目大意:给N个数,有M个查询,问区间[L,R]之间有多少个数与这个区间内的其他数都互质. 思路:dp显然很难搞,既然是求区间就试试每一个数最大可以对答案产生贡献的区间,即预处理出一个数在(lp,rp)内始终与其他数互质的最大区间 则lp和rp分别为左边和右边第一个与他不互质的数的位置 处理的时候素数打表然后从左到右始终更新对于某一个素因子出现的最右的位置然后更新l,r,可以做到 然后就是把查询按l从小到大排序,这样的话每处理一个新的查询,对于在这个查询的 l 左边的数就可以不用考虑了 然后我们

BZOJ 2738 矩阵乘法 整体二分+二维树状数组

题目大意:给定一个矩阵,多次求某个子矩阵中的第k小 分块解法见 http://blog.csdn.net/popoqqq/article/details/41356899 <论除最小割外题目解法从来与题目名称无关系列> 整体二分 Solve(x,y,S)表示处理答案在[x,y]区间内的询问集合S 预先将所有数按照大小排序 每次将[1,mid]之间的数插入树状数组 然后对于分治内部的每一个询问 去树状数组中查询相应子矩阵的数值 如果小于等于k就划分到左集合S1 否则划分到右集合S2 然后Solv

树状数组板子

板子1 板子2 在放板子的代码之前,先讲一下树状数组. 树状数组的作用: 在有修改时可以做到log级别求前缀和 还可以结合差分等神奇的东西食用 空间比线段树要省的多,代码量也少的多 在单点查询的时候比线段树快了不是一点(我真的没有拿线段树的板子去拍这两个题) 我们先来看一下树状数组是个什么东西 首先,我们有一个序列A,其次lowbit(x)表示x的二进制表示中,最低位的1和后面的0构成的数. 树状数组c[i]记录序列A的区间[i-lowbit(i)+1,x]中所有数的和. why?我们画一画树状

树状数组的进阶运用(Stars 数星星)

英文原题 Problem Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the g

Thair数 树状数组

题目: Erwin最近对一种叫"thair"的东西巨感兴趣... 在含有n个整数的序列a1,a2......an中, 三个数被称作"thair"当且仅当i<j<k且ai<aj<ak 求一个序列中"thair"的个数. Input (thair.in) 开始一个正整数n, 以后n个数a1~an. Output (thair.out) "thair"的个数 Sample Input Output 4 2 1