【线段树】单点修改区间求和

作为一个初学线段树的蒟蒻,赶快来瞻仰一下

线段树模板题(一)——单点修改与查询区间和:快速求和计算  

【题目描述】  

给出n个数(1 < = n < = 100000 ),并且初始化所有数字都为0.接下来m次操作,( 1<= m < = 100000 ) 操作有以下两种:

1: C X K 把第X个数的值增加A(A可正可负)

2: P X Y 就是询问 第X个数至 第Y个数 的所有数的和。

【输入】

n m 若干操作

【输出】

对应的输出

【样例输入】

 5 3
C 2 3
C 4 5
P 1 5                           

【样例输出】

8

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define lc (p<<1)
#define rc (p<<1|1)
int n,m;
struct node{
	int l,r,sum;
}T[4*N]; 
void pushup(int p){
	T[p].sum=T[lc].sum+T[rc].sum;
}
void build(int p,int l,int r){//建树
	T[p].l=l;T[p].r=r;
	if(l==r){
		T[p].sum=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	pushup(p);
}
void update(int p,int k,int v){//单点修改 
	if(T[p].l==T[p].r){
		T[p].sum+=v;
		return ;
	}
	int mid=(T[p].l+T[p].r)>>1;
	if(k<=mid)
		update(lc,k,v);
	else
		update(rc,k,v);
	pushup(p);
}
int query(int p,int ql,int qr){//区间求和 
	if(ql<=T[p].l&&qr>=T[p].r)
		return T[p].sum;
	int mid=T[p].l+T[p].r>>1;
	int ans=0;
	if(ql<=mid) ans+=query(lc,ql,qr);
	if(qr>mid) ans+=query(rc,ql,qr);
	return ans;
}
int main(){
	scanf("%d%d",&n,&m);
	build(1,1,100010);
	for(int i=1;i<=m;i++){
		char p; 
		cin>>p;
		if(p=='C'){
			int x,k;
			scanf("%d%d",&x,&k);
			update(1,x,k);
		} 
		else{
			int x,y;
			scanf("%d%d",&x,&y);
			printf("%d\n",query(1,x,y));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42754826/article/details/82817198