这题我用线段树+差分
WA了两个点https://www.luogu.com.cn/record/55829772
我的Code——(注意:请不要管Code中的乘法标记懒得删)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=100006;
ll a[N],tree[N*4],lazymul[N*4],lazyadd[N*4]/*加法标记*/,n,m/*模数*/;
void build(ll i,ll l,ll r)//建树
{ lazymul[i]=1;
if(l==r)
{ tree[i]=a[l];
return;
}
ll mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
tree[i]=(tree[i*2]+tree[i*2+1]);
return;
}
void add1(ll i,ll l,ll r,ll x,ll y)//标记
{ tree[i]=(tree[i]*x+(r-l+1)*y);
lazyadd[i]=(lazyadd[i]*x+y);
lazymul[i]=(lazymul[i]*x);
return;
}
void pushdown(ll i,ll l,ll r)//标记下传
{ ll mid=(l+r)/2;
add1(i*2,l,mid,lazymul[i],lazyadd[i]);
add1(i*2+1,mid+1,r,lazymul[i],lazyadd[i]);
lazyadd[i]=0;
lazymul[i]=1;
return;
}
void addition(ll i,ll l,ll r,ll x,ll y,ll v)//加法
{ if(x<=l&&r<=y)
{ add1(i,l,r,1,v);
return;
}
pushdown(i,l,r);
ll mid=(l+r)/2;
if (x<=mid) addition(i*2,l,mid,x,y,v);
if (mid<y) addition(i*2+1,mid+1,r,x,y,v);
tree[i]=(tree[i*2]+tree[i*2+1]);
}
ll ask(ll i,ll l,ll r,ll x,ll y)//区间询问
{ if(x<=l&&r<=y) return tree[i] ;
pushdown(i,l,r);
ll mid=(l+r)/2,res=0;
if (x<=mid) res+=ask(i*2,l,mid,x,y);
if (mid<y) res+=ask(i*2+1,mid+1,r,x,y);
return res;
}
int main()
{ cin>>n>>m;
for(int i=1;i<=n;i++)
{ cin>>a[i];
}
for(int i=n;i>=1;i--)
{ a[i]=a[i]-a[i-1];
//cout<<a[i]<<" ";
}
//cout<<endl;
build(1,1,n);
while(m--)
{ int x,l,r,k,d;
cin>>x;
if(x==1)
{ cin>>l>>r>>k>>d;
addition(1,1,n,l,l,k);
addition(1,1,n,l+1,r,d);
addition(1,1,n,r+1,r+1,-(k+((r-l)*d)));
}
else
{ cin>>k;
cout<<ask(1,1,n,1,k)<<endl;
}
}
/*for(int i=1;i<=n;i++)
{ cout<<tree[i]<<" ";
}*/
return 0;
}