Big Water Problem----线段树单点修改+区间查询

题目描述
给一个数列,会有多次询问,对于每一次询问,会有两种操作:
1:给定两个整数x, y, 然后在原数组的第x位置上加y;
2:给定两个整数l,r,然后输出数组从第l位加到第r位数字的和并换行

输入描述:
第一行有两个整数n, m(1 <= n, m <= 100000)代表数列的长度和询问的次数
第二行n个数字,对于第i个数字a[i],(0<=a[i]<=100000)。
接下来m行,每一行有三个整数f, x, y。第一个整数f是1或者是2,代表操作类型,如果是1,接下来两个数x,y代表第x的位置上加y,如果是2,则求x到y的和,保证数据合法。
输出描述:
输出每次求和的结果并换行
示例1
输入
复制

10 2
1 2 3 4 5 6 7 8 9 10
1 1 9
2 1 10
输出
复制

64

解析:裸题 单点修改+区间查询

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll tree[N<<2];
ll a[N];
int n,m;
int x,y;
void push_up(int root)
{
	tree[root]=tree[root<<1]+tree[root<<1|1];
}
void build(int root,int l,int r)
{
	if(l==r) 
	{
		tree[root]=a[l];
		return ;
	}
	int mid=l+r>>1;
	build(root<<1,l,mid);
	build(root<<1|1,mid+1,r);
	push_up(root);
}
void update(int root,int l,int r,int x,int y)
{
	if(l==r)
	{
		tree[root]+=y;
		return ;
	}
	int mid=l+r>>1;
	if(x<=mid) update(root<<1,l,mid,x,y);
	else  update(root<<1|1,mid+1,r,x,y);
	push_up(root);
 } 
ll query(int root,int l,int r,int ql,int qr)
 {
 	if(ql<=l&&qr>=r) return tree[root];
 	int mid=l+r>>1;
 	ll res=0;
 	if(ql<=mid) res+=query(root<<1,l,mid,ql,qr);
 	if(qr>mid) res+=query(root<<1|1,mid+1,r,ql,qr);
 	return res;
 }
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	build(1,1,n);
	while(m--)
	{
		int op;
		cin>>op;
		if(op==1)
		{
			cin>>x>>y;
			update(1,1,n,x,y);
		}
		else if(op==2)
		{
			cin>>x>>y;
			cout<<query(1,1,n,x,y)<<endl;
		}
	}
  } 


发布了284 篇原创文章 · 获赞 6 · 访问量 3772

猜你喜欢

转载自blog.csdn.net/qq_43690454/article/details/104049826