您的位置:首页 > 其它

线段树模板

2014-08-01 23:19 239 查看

自用线段树模板,适用于基本线段树和成段更新...

/* *************************************************************** *\
|
| 基础线段树模板
| push_up(),build(),query()为基本线段树函数
| push_down()和update()函数用于成段更新
|
\* *************************************************************** */

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string.h>

using namespace std;

#define maxn 30000				//叶子节点数
#define Mid int mid=(left+right)>>1	//定义mid
#define lson rt*2,left,mid
#define rson rt*2+1,mid+1,right

int n,m;					//n叶子节点数,m询问数
int node[maxn<<2];		//数组开maxn的四倍
int lazy[maxn<<2];			//懒惰标记

void push_up(int rt)			//用于更新节点信息,修改时需要同时修改query()中返回值的处理机制,使二者统一(成段更新时还需修改push_down())
{
node[rt]=node[rt*2]+node[rt*2+1];	//这部分由线段树的作用(求和,求乘积,求最值......)决定
}

void push_down(int rt,int left ,int right)		//懒惰标记下移一层
{
Mid;
lazy[rt*2]+=lazy[rt];
node[rt*2]=node[rt*2]+lazy[rt]*(mid-left+1);
lazy[rt*2+1]+=lazy[rt];
node[rt*2+1]=node[rt*2+1]+lazy[rt]*(right-mid);
lazy[rt]=0;
push_up(rt);
}

void build (int rt ,int left , int right )		//建树
{
if (left==right)
{
scanf("%d",&node[rt]);
return ;
}
Mid;
build (lson);
build(rson);
push_up(rt);
}

void update(int rt ,int left ,int right ,int l,int r,int c)		//用于更新区间[left,right]的节点的值
{
if (l<=left&&right<=r)
{
lazy[rt]+=c;
node[rt]+=c*(right-left+1);
return ;
}
push_down(rt,left,right);
Mid;
if (l<=mid)
update(lson,l,r,c);
if (r>mid)
update(rson,l,r,c);
push_up(rt);
}

int query (int rt ,int left ,int right ,int l,int r)
{
if (l<=left&&right<=r)
{
return node[rt];
}
//push_down(rt,left,right);			//成段更新时使用
Mid;
int ret=0;
if (l<=mid)
ret+=query(lson,l,r);
if (r>mid)
ret+=query(rson,l,r);
return ret;
}

int main()
{
int l,r,flg=0;
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(node,0,sizeof (node));
memset(lazy,0,sizeof (lazy));
build(1,1,n);
for (int i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
printf("%d\n",query(1,1,n,l,r) );
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 模板