贴代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e5+5;
int n,m,tmp[MAXN]/*此处是输入的数组*/,f[MAXN<<2]/*此处是储存线段树区间和的数组*/;
struct node{
int k,d;
}v[MAXN<<2];//懒标记,k是首项,d是公差
void update(int k){
f[k]=f[k+k]+f[k+k+1];//回溯
}
void pushdown(int k,int l,int r){
int mid=(l+r)>>1;
v[k+k].k+=v[k].k;
v[k+k+1].k+=v[k].k+(mid-l)*v[k].d;//因为这里首项改变了,把一个整区间分成左儿子右儿子
v[k+k].d+=v[k].d;//公差不变
v[k+k+1].d+=v[k].d;
f[k+k]=f[k+k]+((mid-l+1)*(v[k+k].k*2+(mid-l)*v[k+k].d))/2;
f[k+k+1]=f[k+k+1]+((r-mid)*(v[k+k+1].k*2+(r-mid-1)*v[k+k+1].d))/2;//更新节点和
v[k].k=0;//置0
v[k].d=0;
}
inline void buildtree(int k,int l,int r){//建树
v[k].k=0,v[k].d=0;
if(l==r){
f[k]=tmp[l];
return ;
}
int mid=(l+r)>>1;
buildtree(k+k,l,mid);
buildtree(k+k+1,mid+1,r);
update(k);
}
inline void add(int k,int l,int r,int x,int y,node z){
if(l==x&&r==y){
f[k]=f[k]+((r-l+1)*(v[k].k*2+(r-l)*v[k].d))/2;
v[k].k+=z.k;//更新标记
v[k].d+=z.d;
return ;
}
pushdown(k,l,r);//下放
int mid=(l+r)>>1;
if(y<=mid){
add(k+k,l,mid,x,y,z);
}
else{
if(x>mid){
add(k+k+1,mid+1,r,x,y,z);
}
else{
add(k+k,l,mid,x,mid,z);
z.k=z.k+(mid-l)*z.d;//这里也是,把一个整区间分成几个子区间的情况
add(k+k+1,mid+1,r,mid+1,y,z);
}
}
update(k);
}
int calc(int k,int l,int r,int p){//calc查询答案
if(l==r){
return f[k];
}
pushdown(k,l,r);
int mid=(l+r)>>1;
if(p<=mid){
return calc(k+k,l,mid,p);
}
else{
return calc(k+k+1,mid+1,r,p);
}
}
signed main(){
std::ios::sync_with_stdio(false);//加速
cin>>n>>m;//读入不解释
for(int i=1;i<=n;i++){
cin>>tmp[i];
}
buildtree(1,1,n);
for(int i=1;i<=m;i++){
int op;
cin>>op;
if(op==1){
int x,y,K,D;
cin>>x>>y>>K>>D;
node t={K,D};
add(1,1,n,x,y,t);
}
else{
int p;
cin>>p;
cout<<calc(1,1,n,p)<<endl;
}
}
return 0;
}