P1438 无聊的数列
对于一个等差数列?
直接维护这个区间的首项和公差就可以了
最后的答案反正只有单点查询(区间也差不多)
返回那个小区间的“首项”就可以了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
struct tr{
int sum;
int fir;
int d;
}tr[400005];
int n,m;
int x;
int a,b,c,d;
void pushup(int ro,int l){
if(tr[ro].d==0&&tr[ro].fir==0){
return ;
}
tr[ro<<1].fir+=tr[ro].fir;
tr[ro<<1].d+=tr[ro].d;
tr[ro<<1|1].d+=tr[ro].d;
tr[ro<<1|1].fir+=tr[ro].d*l+tr[ro].fir;
tr[ro].d=tr[ro].fir=0;
}
void add(int ro,int l,int r,int L,int R,int fi,int d){
if(L<=l&&r<=R){
tr[ro].fir+=fi;
tr[ro].d+=d;
return ;
}
int mid=(l+r)>>1;
pushup(ro,max((long long)0,mid-l+1));
if(L<=mid){
add(ro<<1,l,mid,L,R,fi,d);
}
if(R>mid) {
if(L>mid)
add(ro<<1|1,mid+1,r,L,R,fi,d);
else{
add(ro<<1|1,mid+1,r,mid+1,R,fi+(mid-L+1)*d,d);
}
}
}
int query(int ro,int l,int r,int L,int R){
if(L<=l&&r<=R){
return tr[ro].fir;
}
int mid=(l+r)>>1;
pushup(ro,max((long long)0,mid-l+1));
if(L<=mid){
return query(ro<<1,l,mid,L,R);
}
if(R>mid) return query(ro<<1|1,mid+1,r,L,R);
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;++i){
scanf("%lld",&x);
add(1,1,n,i,i,x,0);
}
for(int i=1;i<=m;++i){
scanf("%lld",&x);
if(x==1){
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
add(1,1,n,a,b,c,d);
}
if(x==2){
scanf("%lld",&x);
cout<<query(1,1,n,x,x)<<endl;
}
}
return 0;
}