线段树区间和(区间修改/区间查询/单点修改/单点查询)

线段树区间和

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,m,p,ans,x,l,r,val;
struct node {
	int l,r,w,f;//f为延迟标记
} tree[4*maxn+5];
void build(int k,int l,int r) { //建树
	tree[k].l=l,tree[k].r=r;
	if(tree[k].l==tree[k].r) {
		scanf("%d",&tree[k].w);
		return;
	}
	int mid=(l+r)/2;
	build(k*2,l,mid);//左孩子
	build(k*2+1,mid+1,r);//右孩子
	tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
void spread(int k) {//延迟标记
	tree[k*2].f+=tree[k].f;
	tree[k*2+1].f+=tree[k].f;
	tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
	tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
	tree[k].f=0;
}
void ask(int k,int x) {//单点查询 ,x为查询位置
	if(tree[k].l==tree[k].r) {
		ans=tree[k].w;
		return;
	}
	if(tree[k].f) spread(k);
	int mid=(tree[k].l+tree[k].r)/2;
	if(x<=mid) ask(2*k,x);
	else ask(2*k+1,x);
}
void change(int k,int x,int val) {//单点修改 x修改位置,val增加的值
	if(tree[k].l==tree[k].r) {
		tree[k].w+=val;//
		return;
	}
	if(tree[k].f) spread(k);
	int mid=(tree[k].l+tree[k].r)/2;
	if(x<=mid) change(2*k,x,val);
	else change(2*k+1,x,val);
	tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
void query(int k,int x,int y) { //区间查询[x,y] 的和
	if(tree[k].l>=x&&tree[k].r<=y) {
		ans+=tree[k].w;
		return;
	}
	if(tree[k].f) spread(k);
	int mid=(tree[k].l+tree[k].r)/2;
	if(x<=mid) query(2*k,x,y);
	if(y>mid) query(2*k+1,x,y);
}

void modify(int k,int x,int y,int val) { //区间修改
	if(tree[k].l>=x&&tree[k].r<=y) {
		tree[k].w+=(tree[k].r-tree[k].l+1)*val;
		tree[k].f+=val;
		return;
	}
	if(tree[k].f) spread(k);
	int mid=(tree[k].l+tree[k].r)/2;
	if(x<=mid) modify(2*k,x,y,val);
	if(y>mid) modify(2*k+1,x,y,val);
	tree[k].w=tree[k*2].w+tree[k*2+1].w;
}

int main() {
	scanf("%d%d",&n,&m);//n个节点,m个操作;
	build(1,1,n);
	while(m--) {
		scanf("%d",&p);
		ans=0;
		if(p==1){//查询节点x的值 ,单点查询 
			scanf("%d",&x);
			ask(1,x);
			printf("%d\n",ans);
		}else if(p==2){//节点x增加val,单点修改 
			scanf("%d%d",&x,&val);
			change(1,x,val);
		}else if(p==3){//区间查询 
			scanf("%d%d",&l,&r);
			query(1,l,r);
			printf("%d\n",ans);
		}else if(p==4){//区间[l,r]都增加val,区间修改 
			scanf("%d%d%d",&l,&r,&val);
			modify(1,l,r,val);
		}
	}
}
/*
9 8
1 2 3 4 5 6 7 8 9
1 5
3 4 8
2 5 100
1 5 
3 4 9
4 2 6 77
1 6
3 1 9

ans:
5
30
105
139
83
530
*/ 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值