一开始的时候也是没有思路,但是看到了考点里有差分
对于区间更新:
- 对 l 位置 +k
- 对区间 [l+1,r] +d
- 对 r+1 位置 -(k+(r-l)*d)
那么单点查询变成了
- a[p]+sum[p](sum[p] 为差分的前缀和)
当然要注意,在更新区间时,要判断 l+1 与 r 的大小关系,以及对 r+1 位置的更新时,可能涉及到第 n+1 个数,所以在建树过程中不妨多开一个点
以下代码无建树过程,因为初始差分值为 0
const int N=1e5+5;
int i,j,k;
int n,m;
int a[N];
struct Node
{
int d,lazy;
Node(int d=0,int lazy=0):d(d),lazy(lazy){}
void update(int x,int len)
{
lazy+=x;
d+=x*len;
}
}t[N<<2];
void push_up(int id)
{
t[id].d=t[id<<1].d+t[id<<1|1].d;
}
void push_down(int id,int L,int R)
{
int x=t[id].lazy;
if(x){
int mid=L+R>>1;
t[id].lazy=0;
t[id<<1].update(x,mid-L+1);
t[id<<1|1].update(x,R-mid);
}
}
void update(int l,int r,int val,int L,int R,int id)
{
if(L>=l && r>=R) t[id].update(val,R-L+1);
else{
int mid=L+R>>1;
push_down(id,L,R);
if(mid>=l) update(l,r,val,L,mid,id<<1);
if(r>=mid+1) update(l,r,val,mid+1,R,id<<1|1);
push_up(id);
}
}
int query(int l,int r,int L,int R,int id)
{
if(L>=l && r>=R) return t[id].d;
else{
int mid=L+R>>1;
push_down(id,L,R);
int ans=0;
if(mid>=l) ans+=query(l,r,L,mid,id<<1);
if(r>=mid+1) ans+=query(l,r,mid+1,R,id<<1|1);
push_up(id);
return ans;
}
}
int main()
{
//IOS;
while(~sdd(n,m)){
for(int i=1;i<=n;i++) sd(a[i]);
int opt,l,r,k,d;
//build(1,n,1);
while(m--){
sdd(opt,l);
if(opt==1){
sddd(r,k,d);
update(l,l,k,1,n,1);
if(r>l) update(l+1,r,d,1,n,1);
update(r+1,r+1,-(k+(r-l)*d),1,n,1);
} else{
int ans=a[l]+query(1,l,1,n,1);
pd(ans);
}
}
}
//PAUSE;
return 0;
}