HDU 1541 Stars(树状数组)

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1541

问题描述

Stars

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12581    Accepted Submission(s): 4945


 

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

http://acm.hdu.edu.cn/data/images/1541-1.jpg

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

 

Source

Ural Collegiate Programming Contest 1999

------------------------------------------------------------

题意

定义x-y坐标上的一个点的level = x,y ≤  该点x,y坐标的点的个数(不会有2个点坐标完全相同)。给定n个点,按y坐标的升序排序,y坐标相同的点按x坐标的升序排序,计算level = 0,1,…,n-1的点的个数,分成n行输出。

------------------------------------------------------------

思路

树状数组模板题。关于树状数组理论参见博文:树状数组的原理和实现

此题如果直接模拟,复杂度为O(N^2). 考虑到有频繁求和,故可以采用树状数组,复杂度为O(NlogN).

由于每个点的y坐标按y升序,故如果B点的序号小于A点且B点的x坐标也小于A点,则B点一定对A点的level有贡献。基于此,用x轴作为树状数组的下标索引,用树状数组数据结构中的“A数组”的A[i]表示“x坐标小于等于i的点个数”,“C数组”表示树状数组。另外用一个长度为n的结果数组a数组a[i]表示“level = i的点的个数”。每读入一个点的坐标(x,y),计算一次树状数组前x项和,写入结果数组,再更新树状数组。

此题有2个坑点,如果没想到会WA或TLE:

1. 虽然题目中没有说,但此题是多组测试数据

2. 此题中X可能为0,因为树状数组lowbit(0) = 0,会陷入死循环,所以要把输入的x都+1

------------------------------------------------------------

代码

#include<cstdio>
#include<cstring>

const int NMAX = 15005;
const int XMAX = 32005;
const int XBOUND = 32000;

int a[NMAX] = {};		// 结果数组 
int c[XMAX] = {};		// 树状数组(防止出现0,所有x都+1) 

// 树状数组3函数
// lowbit: k=n的二进制末尾0的个数,求n的2^k
int lowbit (int n)
{
	return n & (-n);	
}

// modify: 修改树状数组c中索引为x的元素的值,增加d 
void modify (int x, int d) 
{
	if (x < 1)
	{
		return;
	}
	else
	{
		while (x <= XBOUND+1)
		{
			c[x] += d;
			x += lowbit(x);
		} 
	}
}

// getsum: 求sum(n) = x坐标等于n的星星数量 
int getsum(int n)
{
	int ans = 0;
	while (n > 0)
	{
		ans += c[n];
		n -= lowbit(n);
	}
	return ans;
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("1541.txt", "r", stdin);
	#endif
	int n, i, x, y;
	while(scanf("%d", &n)!=EOF)
	{
		memset(c,0,sizeof(c));		// 清空树状数组 
		memset(a,0,sizeof(a));		// 清空结果数组 
		for (i=0; i<n; i++)
		{
			scanf("%d%d", &x, &y);	// 输入x可能有0,将所有x映射为x+1 
			a[getsum(x+1)]++;		// level==getsum(x+1)的星星个数++ 
			modify(x+1, 1);			// 树状数组x位置 +1
		}
		for (i=0; i<n; i++)
		{
			printf("%d\n", a[i]);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/81515724
今日推荐