w20810的专栏

人若无名,方可专心练剑

树状数组入门

用office做了一张pdf - -


























这是一维的情形,如果是二维,可以把每一行的一维树状数组看成一个节点,然后再把二维树状数组看成一维树状数组。

好文章:https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/#prob


两道入门题:http://acm.hdu.edu.cn/showproblem.php?pid=1556

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


对于第一题HDU1556:

题意:初始数组元素值都为0,给定区间[x,y],将区间[x,y]每个元素的值+1,最后输出整个数组每个元素的值。


更新区间[x,y]的话,可以只更新两个点x,y+1(将所有管辖x的管辖点+1,所有管辖y+1的管辖点-1)

查询点p,将p管辖的区间的值加起来就行了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int a[100005],N;

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

void update(int x,int v)
{
    while(x && x<=N)
    {
        a[x]+=v;
        x+=lowbit(x);
    }
}

int query(int x)
{
    int ret=0;
    while(x>0)
    {
        ret+=a[x];
        x-=lowbit(x);
    }
    return ret;
}

int main()
{
    int i,j,x,y;
    while(scanf("%d",&N),N)
    {
        memset(a,0,sizeof(a[0])*(N+2));
        for(i=1;i<=N;i++)
        {
            scanf("%d%d",&x,&y);
            update(x,1);
            update(y+1,-1);
        }
        for(i=1;i<N;i++)
            printf("%d ",query(i));
        printf("%d\n",query(N));
    }
    return 0;
}
这题不是边更新边查询,所以可以用更简单的方法做。由于是更新完再查询,可以在每次更新的时候将两个端点标记一下,左后再统一更新一遍就行了。

代码:

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int s[100005]; 

int main()
{
    int n,x,y,i;
    while(scanf("%d",&n),n)
    {
        memset(s,0,sizeof(s));
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            s[x-1]--;
            s[y]++;
        }
        for(i=n-1;i>=1;i--)
            s[i]+=s[i+1];
        for(i=1;i<n;i++)
            printf("%d ",s[i]);
        printf("%d\n",s[n]);
    }
    return 0;
}

对于第二题POJ2155:

题意:给定一个N*N的矩阵,矩阵上每个元素的初始值为0,有两种操作①给出一个子矩阵(左上角和右下角的坐标),将子矩阵的每个元素的值取反②查询一个元素的值


由于每次查询的答案只有0和1,可以统计每个元素被修改过多少次,如果为奇数次那么答案为1,否则为0。修改和查询几乎和上面那题一样,只是多了一维。

代码:

#include <iostream>
#include <cstdio>

using namespace std;

int N,a[1006][1006];

void Clear()
{
	for(int i=0;i<=N+1;i++)
		for(int j=0;j<=N+1;j++)
			a[i][j]=0;
}

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

void update(int x,int y,int v)
{
	for(int i=x;i<=N;i+=lowbit(i))
		for(int j=y;j<=N;j+=lowbit(j))
			a[i][j]+=v;
}

int query(int x,int y)
{
	int ret=0;
	for(int i=x;i>0;i-=lowbit(i))
		for(int j=y;j>0;j-=lowbit(j))
			ret+=a[i][j];
	return ret;
}

int main()
{
	int ncase,q,x1,x2,y1,y2;
	char str[2];
	scanf("%d",&ncase);
	for(int i=1;i<=ncase;i++)
	{
		scanf("%d%d",&N,&q);
		Clear();
		while(q--)
		{
			scanf("%s",str);
			if(str[0]=='C')
			{
				scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
				update(x1,y1,1);
				update(x2+1,y1,-1);
				update(x1,y2+1,-1);
				update(x2+1,y2+1,1);
			}
			else
			{
				scanf("%d%d",&x1,&y1);
				printf("%d\n",query(x1,y1)%2);
			}
		}
		printf("\n");
	}
	return 0;
}


阅读更多
版权声明:转吧。 https://blog.csdn.net/w20810/article/details/46778097
文章标签: 树状数组
个人分类: ACM-数据结构
上一篇CF 305 div2 E. Mike and Foam (容斥原理)
下一篇LA4328 Ping Pong (树状数组)
想对作者说点什么? 我来说一句

树状数组课件

2012年07月14日 2.01MB 下载

树状数组树状数组资料下载

2010年05月03日 411KB 下载

树状数组的ppt(简单易懂)

2010年04月26日 610KB 下载

线段树 树状数组 数据结构

2011年07月24日 1.29MB 下载

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

关闭
关闭