线段树模板1

#include
const int MAXN =2e5+5;
typedef long long ll;	//次模板一般用于大数据,开long long 
int numbers[MAXN];
struct node{
	int l=0,r=0;//左 右结点 
	int val=0;//该点的值 
}tree[MAXN*4];			//
/*
模板大意:对n个数,进行m次操作,操作有两种情况,
修改某一结点的值,或者查询某个区间的和.
*/ 
void build_SegmentTree(int l,int r,int p)/*l,r分别是区间上下界,
                                        p是树中该节点在完全二叉树的序号 */
{
	tree[p].l=l;		//给给结点附上左右孩子索引 
	tree[p].r=r;
	if(l==r) 		//该结点是叶子结点,把它对应的numbers的值赋给它 
	{
		tree[p].val=numbers[l];
		return ;	//终止 
	}
	else
	{
		int mid=(l+r)/2,pl=2*p,pr=pl+1;			//二分l,r得到两个区间 
		build_SegmentTree(l,mid,pl);			//建立左 
		build_SegmentTree(mid+1,r,pr);		//建立右 
		tree[p].val=tree[pr].val+tree[pl].val;	//两个区间和相加 
		return ;
	}
}
void UpDate(int qidian,int x,int y)	//x是位置,y是更新值 
{
	if(tree[qidian].l==tree[qidian].r)	//找到这个叶子结点 
	{
		tree[qidian].val=y;
		return ;
	}
	
	int mid=(tree[qidian].l+tree[qidian].r)/2,l=qidian*2,r=l+1;
	if(x<=mid)											//更新左边
	{
		UpDate(l,x,y);
	}
	else 
	{
		UpDate(r,x,y);									更新右边
	}
	tree[qidian].val=tree[r].val+tree[l].val;	//更新父节点的值 
	return ;
} 
int Search(int qidian,int x,int y)	//x,y是要查找的上下限 
{
	if(tree[qidian].l>=x&&tree[qidian].r<=y)	//在起点范围之内 
	{
		return tree[qidian].val;
	}
	int val=0;
	int mid=(tree[qidian].r+tree[qidian].l)/2,ql=qidian*2,qr=ql+1;
	if(x<=mid)						//找左边在需查找范围内的值 
	{
		val+=Search(ql,x,y);
	}
	if(y>mid)
	{
		val+=Search(qr,x,y);
	}
	return val;
}
int main()
{
	int m,n;
	scanf("%d %d",&n,&m); 
	for(int i=1;i<=n;i++)	//从1开始,方便建树 
	{
		scanf("%d",&numbers[i]);
	}
	
	build_SegmentTree(1,n,1);	//建树过程依开始的numbers数组中的元素
	int xuanxiang,x,y;
	scanf("%d %d %d",&xuanxiang,&x,&y);
	while(m--) {
	if(xuanxiang==0)		//修改 
	{
		UpDate(1,x,y);
	}
	else					//查询 
	{
		if(x>y)
		{
			int t=x;
			x=y;
			y=t;
		}
		int result=Search(1,x,y);
		printf("\n查询的结果是:%d",result);
	} 
}
}

你可能感兴趣的:(算法)