您的位置:首页 > 其它

hdu1541 Stars(树状数组+解释)

2016-04-28 08:35 411 查看
http://acm.hdu.edu.cn/showproblem.php?pid=1541

题意:有n个星星,输入时是以从下到上,从左到右的方式输入(x,y)的值。每个星星左下方有多少个星星就评多少等级,求0~n-1个等级分别有多少个星星。

思路:树状数组入门题,第二次做。首先上博客,这篇写的很好,看完就懂了。树状数组主要用的是二进制思想,相比于普通数组在更新和求和上从O(n)优化到了O(n-1)。

本题要求的是每个星星左下方有多少个星星,因为后遍历的肯定是上方,所以只需求出左边有多少个星星。这样我们把每个星星量化为一个,求左边有多少星星就是求和。这里每组最多15000个星星,还有多组,普通数组耗时过多。这样就用到了树状数组。树状数组那个大牛解释的很好了,不过为了巩固还是要写些注释。

这里我把每个lowbit换成了组的说法。

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

using namespace std;

typedef long long ll;
const int N = 32001;

int tree
;//从当前元素开始连续往左求lowbit(x)个数的和
int level
;//保存等级

int lowbit(int x)
{
return -x&x;
}

void add(int x)//更新
{
while(x < N)//临界值32001,代表某一项改变临界区内相应组的值也要改变
{
tree[x]+=1;//涉及到的组加一,代表多一个等级(类似于打表)
x+=lowbit(x);//去尾操作,变成下一个被涉及到的组
}
}

int sum(int x)
{
int rankk = 0;//星星的等级就相当于总和,每个星星左边有多少个星星,等级即为多少
while(x > 0)//说明还有组可加
{
rankk+=tree[x];//总星数加上本星星左方每组有多少星星
x-=lowbit(x);//用二分递减的规则使x变成下一组
}
return rankk;
}

int main()
{
// freopen("in.txt", "r", stdin);
int n, x, y;
while(~scanf("%d", &n))
{
memset(level, 0, sizeof(level));
memset(tree, 0, sizeof(tree));
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &x, &y);
level[sum(++x)]++;
add(x);
}
for(int i = 0; i < n; i++)
printf("%d\n", level[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu