线段树

(待补充

#include<bits/stdc++.h>
using namespace std;
const int N=500010;
struct node {
	int l,r;
	int val;
} t[4*N]; //4倍空间
int a[N];//存数
int n,p,q;
long long ans;
void build(int p,int l,int r) { //建树
	t[p].l=l;
	t[p].r=r;//赋值,确定左右端点
	if(t[p].l==t[p].r) { //重复,即叶子节点
		t[p].val=a[l];//赋值
		return ;
	}
	int mid=(l+r)/2;//中点
	if(l<=mid)build(p*2,l,mid);//建左子树
	if(r>mid)build(p*2+1,mid+1,r);//建右子树
	t[p].val=t[p*2].val+t[p*2+1].val;//算区间和
}

void change(int p,int x,int k) { //改数值
	int l=t[p].l,r=t[p].r;//提取左右值
	if(l==r) { //找到目标位置(叶子节点)
		t[p].val+=k;//加上
		return ;
	}
	int mid=(l+r)/2;
	if(x<=mid)change(p*2,x,k);//如果在左边搜左子树
	else change(p*2+1,x,k);//其他情况搜右子树
	t[p].val=t[p*2].val+t[p*2+1].val;//更新区间和
}
void query(int p,int l,int r) { //找区间和
	if(t[p].l>=l&&t[p].r<=r) { //在范围内就不用往下搜了
		ans=ans+t[p].val;
		return ;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(mid>=l)query(p*2,l,r);//如果左子树在区间范围内就搜下去
	if(r>mid)query(p*2+1,l,r);//右边同理
}

int main() {
	scanf("%d%d%d",&n,&p,&q);
	for(int i=1; i<=n; i++)scanf("%d",&a[i]);
	build(1,1,n);//从根节点开始建树,区间范围是1-n

	for(int i=1; i<=p; i++) {
		int xd,dx;
		cin>>xd>>dx;//加上一个数 
		change(1,xd,dx);
		}

	for(int i=1; i<=q; i++) {
		int xd,dx;
		cin>>xd>>dx;
		ans=0;
		query(1,xd,dx);
		cout<<ans<<endl;//求区间和 
	}


	return 0;
}
posted @ 2021-11-16 20:07  Hi_Kou  阅读(44)  评论(0)    收藏  举报