#include<iostream>
#include<vector>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int n,p,a,b,m,x,y,ans;
struct node
{
int l,r,w,f;
} tree[400005];
void build(int k,int ll,int rr)//建树
{
tree[k].l=ll;
tree[k].r=rr;
if(tree[k].l==tree[k].r)
{
scanf("%d",&tree[k].w);
return ;
}
int m=(ll+rr)/2;
build(k*2,ll,m);
build(k*2+1,m+1,rr);
tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
void down(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 point(int k)//单点查询
{
if(tree[k].l==tree[k].r)
{
ans=tree[k].w;
return ;
}
if(tree[k].f)
down(k);
int m=(tree[k].l+tree[k].r)/2;
if(x<=m)
point(k*2);
else
point(k*2+1);
}
void change_point(int k)//单点修改
{
if(tree[k].l==tree[k].r)
{
tree[k].w+=y;
return ;
}
if(tree[k].f)
down(k);
int m=(tree[k].l+tree[k].r)/2;
if(x<=m)
change_point(k*2);
else
change_point(k*2+1);
tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
void interval(int k)// 区间查询
{
if(tree[k].l>=a&&tree[k].r<=b)
{
ans+=tree[k].w;
return ;
}
if(tree[k].f)
down(k);
int m=(tree[k].l+tree[k].r)/2;
if(a<=m)
interval(k*2);
if(b>m)
interval(k*2+1);
}
void change_interval(int k)//区间修改
{
if(tree[k].l>=a&&tree[k].r<=b)
{
tree[k].w+=(tree[k].r-tree[k].l+1)*y;
tree[k].f+=y;
return ;
}
if(tree[k].f)
down(k);
int m=(tree[k].l+tree[k].r)/2;
if(a<=m)
change_point(k*2);
if(b>m)
change_interval(k*2+1);
tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
int main()
{
scanf("%d",&n);
build(1,1,n);
scanf("%d",&m);
for(int i=1; i<=m; i++)
{
scanf("%d",&p);
ans=0;
if(p==1)
{
scanf("%d",&x);
point(1);
printf("%d\n",ans);
}
else if(p==2)
{
scanf("%d %d",&x,&y);
change_point(1);
}
else if(p==3)
{
scanf("%d %d",&a,&b);
interval(1);
printf("%d\n",ans);
}
else
{
scanf("%d%d%d",&a,&b,&y);
change_interval(1);
}
}
}
线段树(模板)
最新推荐文章于 2021-09-22 13:56:43 发布