P3374 【模板】树状数组 1 线段树解题
P3374 【模板】树状数组 1
题解:
线段树的单点更新,区间查询,注意线段树的结点个数是原数组的4倍
#include<iostream>
#include<cstdio>
using namespace std;
long long s[2000100],a[501000],n,m,dx,dy;
void btr(int rt,int l,int r)//建树
{
if(l==r)//叶结点等于原数组的值
{
s[rt]=a[l];
}
else
{
int ls=rt*2,rs=rt*2+1,mid=(l+r)/2;//二分递归求左右子树
btr(ls,l,mid);
btr(rs,mid+1,r);
s[rt]=s[ls]+s[rs];//回溯求该结点的和
}
}
void su(int x,int k,int rt,int l,int r)//单点更新
{
if(l==r)
{
s[rt]+=k;
return;
}
int mid=(l+r)/2,ls=rt*2,rs=rt*2+1;
if(x>=l&&x<=mid)
{
su(x,k,ls,l,mid);
}
else
{
su(x,k,rs,mid+1,r);
}
s[rt]+=k;
}
long long sc(int x,int y,int rt,int l,int r)//区间查询,查询区间[x,y],结点rt,对应区间[l,r]
{
if(l>=dx&&r<=dy)//查询区间包括结点区间直接返回
{
return s[rt];
}
long long ans=0;
int mid=(l+r)/2,ls=rt*2,rs=rt*2+1;
if(y<=mid)//只有左子树
{
ans+=sc(x,y,ls,l,mid);
}
else if(x>mid)//只在右子树
{
ans+=sc(x,y,rs,mid+1,r);
}
else//两个均包括
{
ans=ans+sc(x,mid,ls,l,mid)+sc(mid+1,y,rs,mid+1,r);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
btr(1,1,n);
for(int i=1;i<=m;i++)
{
int x,y,c;
cin>>c>>x>>y;
if(c==1)
{
su(x,y,1,1,n);
}
else
{
dx=x;dy=y;
cout<<sc(x,y,1,1,n)<<endl;
}
}
}
浙公网安备 33010602011771号