现在的位置: 首页 > 综合 > 正文

poj 2352 Stars(树状数组基础)

2014年04月05日 ⁄ 综合 ⁄ 共 1656字 ⁄ 字号 评论关闭

http://poj.org/problem?id=2352

题意:有若干个星星,给出每个星星在二维平面上的坐标(输入按y递增顺序给出,y相同时按x递增顺序输出)。定义每个星星的级别为 横纵坐标均不超过自己的星星的个数(不包括自身)。问级别为0~n-1的星星分别有几个。

思路:首先将二维转化为一维。。因为输入是有顺序的,当前星星与后面的星星并没有关系。对于第i次输入的星星(横纵坐标为x,y),只需统计前i-1个中横坐标小于x的星星的个数。树状数组可以很高效的进行区间统计。不过,树状数组的下标从1开始,所以当题目中输入x = 0时,要执行x++,相当于所有坐标右移,但相对位置不变。


#include <stdio.h>
#include <string.h>

const int maxn = 32001;
int level[maxn];
int c[maxn];

int Lowbit(int x)
{
	return x&(-x);
}
int sum(int end)
{
	int s = 0;
	while(end > 0)
	{
		s += c[end];
		end -= Lowbit(end);
	}
	return s;
}

void update(int pos)
{
	while(pos <= maxn)
	{
		c[pos]++;
		pos += Lowbit(pos);
	}
}

int main()
{
	int n,x,y;
	scanf("%d",&n);
	memset(level,0,sizeof(level));
	memset(c,0,sizeof(c));

	for(int i = 0; i < n; i++)
	{
		scanf("%d %d",&x,&y);
		level[sum(x+1)] ++;
		update(x+1);
	}
	for(int i = 0; i < n; i++)
		printf("%d\n",level[i]);
	return 0;
}

区间统计也可以用线段树实现。。不过树状数组跑的比线段树快,但只要树状数组可以实现的线段树均能实现。

#include <stdio.h>
#include <string.h>

const int maxn = 32002;

struct line
{
	int l;
	int r;
	int num;
}tree[maxn<<2];

int level[maxn];

void build(int v, int l, int r)
{
	tree[v].l = l;
	tree[v].r = r;
	tree[v].num = 0;
	if(l == r)
		return;
	int mid = (l+r)>>1;
	build(v*2,l,mid);
	build(v*2+1,mid+1,r);
}
//查询区间1~x
int query(int v, int l, int r)
{
	if(tree[v].l == l && tree[v].r == r)
		return tree[v].num;

	int mid = (tree[v].l + tree[v].r)>>1;
	if(r <= mid)
		return query(v*2,l,r);
	else
	{
		if(l > mid)
			return query(v*2+1,l,r);
		else
			return query(v*2,l,mid) + query(v*2+1,mid+1,r);
	}
}
//单点更新 pos
void update(int v, int pos)
{
	tree[v].num++;
	if(tree[v].l == tree[v].r)
		return;
	int mid = (tree[v].l + tree[v].r)>>1;
	if(pos <= mid)
		update(v*2,pos);
	else update(v*2+1,pos);
}

int main()
{
	int n;
	int x,y;
	memset(level,0,sizeof(level));

	scanf("%d",&n);
	build(1,1,32001);	//建树

	for(int i = 1; i <= n; i++)
	{
		scanf("%d %d",&x,&y);
		x++;
		level[ query(1,1,x) ]++;
		update(1,x);
	}

	for(int i = 0; i < n; i++)
	{
		printf("%d\n",level[i]);
	}
	return 0;

}

抱歉!评论已关闭.