[POJ] 2352 Stars [线段树区间求和]

Stars

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 given star. Astronomers want to know the distribution of the levels of the stars. 

For example, look at the map shown on the figure above. Level of the star number 5 is equal to 3 (it‘s formed by three stars with a numbers 1, 2 and 4). And the levels of the stars numbered by 2 and 4 are 1. At this map there are only one star of the level 0, two stars of the level 1, one star of the level 2, and one star of the level 3.

You are to write a program that will count the amounts of the stars of each level on a given map.

Input

The first line of the input file contains a number of stars N (1<=N<=15000). The following N lines describe coordinates of stars (two integers X and Y per line separated by a space, 0<=X,Y<=32000). There can be only one star at one point of the plane. Stars are listed in ascending order of Y coordinate. Stars with equal Y coordinates are listed in ascending order of X coordinate.

Output

The output should contain N lines, one number per line. The first line contains amount of stars of the level 0, the second does amount of stars of the level 1 and so on, the last line contains amount of stars of the level N-1.

Sample Input

5
1 1
5 1
7 1
3 3
5 5

Sample Output

1
2
1
1
0

Hint

This problem has huge input data,use scanf() instead of cin to read data to avoid time limit exceed.

Source

Ural Collegiate Programming Contest 1999

题目大意:

在坐标上有n个星星,如果某个星星坐标为(x, y), 它的左下位置为:(x0,y0),x0<=x 且y0<=y。如果左下位置有a个星星,就表示这个星星属于level x

按照y递增,如果y相同则x递增的顺序给出n个星星,求出所有level水平的数量。

 

分析与总结:

因为输入是按照按照y递增,如果y相同则x递增的顺序给出的, 所以,对于第i颗星星,它的level就是之前出现过的星星中,横坐标x小于等于i星横坐标的那些星星的总数量(前面的y一定比后面的y小)。

所以,需要找到一种数据结构来记录所有星星的x值,方便的求出所有值为0~x的星星总数量。

树状数组和线段树都是很适合处理这种问题。

 1 #include<cstdio>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 #define clr(x,y)    memset(x,y,sizeof(x))
 6 #define lson        l,m,rt<<1
 7 #define rson        m+1,r,rt<<1|1
 8
 9 const int maxn=4e4;
10 int maxi,sum[maxn<<2],num[maxn];
11
12 struct node
13 {
14     int x,y;
15 } star[maxn];
16
17 void PushUp(int rt)
18 {
19     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
20 }
21
22
23 void Updata(int x,int l,int r,int rt)
24 {
25     int m;
26
27     if(l==r) {
28         sum[rt]++;
29         return;
30     }
31
32     m=(l+r)>>1;
33     if(x<=m) Updata(x,lson);
34     else     Updata(x,rson);
35
36     PushUp(rt);
37 }
38
39 int query(int L,int R,int l,int r,int rt)
40 {
41     int m,ret=0;
42
43     if(L<=l && r<=R) {
44         return sum[rt];
45     }
46
47     m=(l+r)>>1;
48     if(L<=m) ret+=query(L,R,lson);
49     if(R>m)  ret+=query(L,R,rson);
50
51     return ret;
52 }
53
54
55
56 int main()
57 {
58     int n,ans;
59
60     maxi=-1;
61     clr(sum,0);clr(num,0);
62     scanf("%d",&n);
63     for(int i=0;i<n;i++) {
64         scanf("%d%d",&star[i].x,&star[i].y);
65         if(star[i].x>maxi) maxi=star[i].x;
66     }
67
68     for(int i=0;i<n;i++) {
69         ans=query(0,star[i].x,0,maxi,1);
70         Updata(star[i].x,0,maxi,1);
71         num[ans]++;
72     }
73
74     for(int i=0;i<n;i++) {
75         printf("%d\n",num[i]);
76     }
77
78
79     return 0;
80 }
时间: 2024-08-03 20:50:11

[POJ] 2352 Stars [线段树区间求和]的相关文章

POJ 2352 Stars 线段树

题目链接 题意:在一个二维平面上有n个星星,每个星星的等级为x,x为该星星左方和下方所包含的星星的数量(包含正左和正下的),输出每个等级各有多少星星,星星坐标按照y序递增给出,y值相同按照x递增给出. 题解:因为已经排好序了,我们每次更新加查询就可以了,因为后加入的一定是下方或者同行的,查询一下是不是左面的就行了.可以用线段树或者树状数组做,注意建树是N不是n,区间更新问题好像可以用什么lazy标记,这道题主要考察的还是思路.注意本题是按照值来进行查询的,建树的时候要用N建树. #include

POJ 3468 线段树区间求和

线段树区间求和树节点不能只存和,只存和,会导致每次加数的时候都要更新到叶子节点,速度太慢(O(nlogn)).所以我们要存两个量,一个是原来的和nSum,一个是累加的增量Inc. 在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新nSum(加上本次增量),再将增量往下传,这样更新的复杂度就是O(log(n)). 在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc清0,接下来再往下查询. Inc往下带的过程也是区间分解的过程,复杂

POJ 2823 Sliding Window 线段树区间求和问题

题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 还有一种做法是单调队列,耗时更少. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define N 1000005 using namespace std; int

线段树 区间求和 poj 3468 A Simple Problem with Integers

题意: 给n个整数,求两种操作:1.给一个区间的数都加上一个数 2.查询一个区间的数的和  ,输出每次查询的结果 线段树区间求和,注意点: 1.使用lazy操作pushdown的时候,应该是子节点的lazy值加上父节点的lazy值,而不是直接赋值成父节点的lazy值,因为子节点可能之前也被操作过 2.节点的sum求和的时候应该加上区间的和(虽然直接加上修改值也能过样例TAT) 3.sum应该用long long 代码: #include <cstdlib> #include <cctyp

HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和 由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是

HDU 4027 Can you answer these queries? (线段树区间求和)

Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submission(s): 12290    Accepted Submission(s): 2912 Problem Description A lot of battleships of evil are arranged in a line before

POJ 3667(线段树区间合并)

http://poj.org/problem?id=3667 题意:两个操作 : 1 选出靠左的长度为a的区间. 2 把从 a到a+b的区间清空. 线段树区间合并+lazy // by caonima // hehe #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; co

hdu 1541/poj 2352:Stars(树状数组,经典题)

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

poj 3468(简单线段树区间更新)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 61936   Accepted: 18934 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of