线段树2023/4/27

描述

如题,已知一个数列,你需要进行下面两种操作:

  • 将某一个数加上x

  • 求出某区间每一个数的和

输入

第一行包含两个正整数n,m,分别表示该数列数字的个数和操作的总个数。

第二行包含n个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来m行每行包含3个整数,表示一个操作,具体如下:

  • 1 x k含义:将第x个数加上k

  • 2 x y含义:输出区间[x,y]内每个数的和

输出

输出包含若干行整数,即为所有操作2的结果。

输入样例 1 

5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4

输出样例 1

14
16

提示

1<=(n,m,k)<=5e5

1<=x<=y<=n

#include <iostream>
#define int long long
using namespace std;
const int N = 5e5+10;
struct segmentTree
{
	int l,r;
	int sum;
} t[N<<2];
int a[4*N];
void pushup(int p)//向上更新,修改某个节点后,将所有祖先节点中存储的信息都更新一遍 
{
	t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
}
void build(int p,int l,int r)//构建整颗线段树 
{
	t[p]={l,r};//记录当前节点的左右端点 
	if(l==r)
	{
		t[p].sum=a[l];//将该节点存储的信息设为对应位置上的函数值 
		return;
	}
 	//如果不是叶子节点就继续递归构建它的左右子节点 
	int mid=(l+r)>>1;
	build(p<<1,l,mid),build(p<<1|1,mid+1,r);
	pushup(p);//最后更新当前节点的信息 
}
void modify(int p,int v,int k)//修改线段树中某个位置上的函数
                            // p为当前需要修改的结点的编号 
                            //v为要修改的元素的下标
							//k为要加上的函数值 
{
	if(t[p].l==t[p].r&&t[p].l==v)
	{
		t[p].sum+=k;
		return;
	}
	int mid=(t[p].l+t[p].r)>>1;//继续向它的子节点中搜索 
	if(v<=mid) modify(p<<1,v,k);//修改左子节点的信息 
	else modify(p<<1|1,v,k);//修改右子节点的信息 
	pushup(p);//更新祖先节点的信息 
}
int query(int p,int l,int r)//查询某个区间的信息,l和r表示需要查询的区间 
{
	if(t[p].r<=r&&t[p].l>=l)//先判断前节点的区间是否包含要查询的区间 
	{
		return t[p].sum;
	}
	int mid=(t[p].l+t[p].r)>>1;
	int res=0;
	if(r<=mid) res+=query(p<<1,l,r);
	else if(l>mid) res+=query(p<<1|1,l,r);
	else res+=query(p<<1,l,mid)+query(p<<1|1,mid+1,r);
	return res;
}
signed main()
{
	int n,m;
	cin >> n >> m;
	for(int i = 1;i <= n;i ++)
	{
		cin >> a[i];
	}
	build(1,1,n);
	while(m --)
	{
		int op;
		cin >> op;
		if(op==1)
		{
			int x,k;
			cin >> x >> k;
			modify(1,x,k);
		}
		else
		{
			int l,r;
			cin >> l >> r;
			printf("%lld\n",query(1,l,r));
		}
	 } 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值