【poj 2352】 Stars 及浅谈树状数组

树状数组:

       1、 一个可以动态维护前缀和的一个数据结构,支持求和和单点修改。在拓展情况下可以支持区间修改。
       2、 优点:代码短,O(lgn)的开销

lowbit是非常有用的 x&(-x) 利用补码的性质得出最低位的数字。


核心代码:

inline int lowbit(int x){ return x&(-x);}
void add(int x,int val)
{
	/* 修改 a[x] */ 
	for (int i = x ; i < maxn ; i += lowbit(i) )
		node[i] += val; 
} 
int get(int x){
	/* 求a[1] + a[2] + ... a[x] */ 
	int sum = 0;
	for (int i = x ; i ; i -= lowbit(i))
		sum += node[i];
	return sum; 


单点修改RMQ就不讲了实在是太容易了。


POJ 2352

给出按照y升序,y相同x升序的有序数列,

分别统计: 在某个坐标左下(包括左、下)有1~n个坐标的个数


分析:

       1、 当y相同时,很明显,求在这个区间内的和就可以了。

       2、 当y大,而x小的时候:我们求的是什么?想一想,也就是我们求的时之前横坐标值为1~x的坐标总数,从这个道理上讲,求(y,x)和求(y+1,x)并没有本质区别。因此,我们只要像1一样求和就可以了。

        3、求和结束后插入新的节点,值位y

       4、在维护前缀的时候有不干涉后面情况的性质,因此可以使用树状数组


#include <iostream>
#include <cstring>
using namespace std;
#define maxn 32222 
int node[maxn];
int levels[maxn];
inline int lowbit(int x){ return x&(-x);}
void add(int x,int val)
{
	/* 修改 a[x] */ 
	for (int i = x ; i < maxn ; i += lowbit(i) )
		node[i] += val; 
} 
int get(int x){
	/* 求a[1] + a[2] + ... a[x] */ 
	int sum = 0;
	for (int i = x ; i ; i -= lowbit(i))
		sum += node[i];
	return sum; 
}

int main(){  
    int n,x,y;  
    while(~scanf("%d",&n)){  
        memset(levels,0,sizeof(levels));  
        int tt=n;  
        while(tt--){  
            scanf("%d%d",&x,&y);  
            x++;
            levels[get(x)]++;  
            add(x,1);  
        }  
        for(int i=0;i<n;i++) printf("%d\n",levels[i]);  
    }  
}  

      

阅读更多
个人分类: 【数据结构】
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭