传送门

算是一道非常经典的题,首先,看见等差数列就要下意识地想到差分,考虑把原序列转换为差分序列,发现查询操作就转化为查询前缀和,在区间[l,r][l,r]加上等差数列就相当于区间[l+1,r][l+1,r]加上公差,在ll上加上首项,最需要注意的是加上等差数列的操作不影响rr后面的数,于是在r+1r+1 的位置要减去k+d×(rl)k+d \times (r-l),抵消前面的影响。

#include <bits/stdc++.h>
#define MAXN 200005
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=(x<<3)+(x<<1)+(ch^'0');
        ch=getchar();
    }
    return x*f;
}
int b[MAXN],a[MAXN],temp[MAXN];
namespace SegmentTree{
    struct node{
        int l,r;
        int val,tag;
        inline int len(){return r-l+1;}
    }tree[MAXN<<2];
    #define lc i<<1
    #define rc i<<1|1
    inline void pushup(int i){
        tree[i].val=tree[lc].val+tree[rc].val;
    }
    inline void Change(int i,int val){
        tree[i].val+=val*tree[i].len();
        tree[i].tag+=val;
    }
    inline void pushdown(int i){
        if (tree[i].tag){
            Change(lc,tree[i].tag);
            Change(rc,tree[i].tag);
            tree[i].tag=0;
        }
    }
    void Build(int i,int l,int r){
        tree[i].l=l,tree[i].r=r;
        if (l==r){
            tree[i].val=a[l];
            return ;
        }
        int mid=(l+r)>>1;
        Build(lc,l,mid);
        Build(rc,mid+1,r);
        pushup(i);
    }
    void Update(int i,int L,int R,int val){
        if (L<=tree[i].l&&tree[i].r<=R){
            Change(i,val);
            return ;
        }
        pushdown(i);
        int mid=(tree[i].l+tree[i].r)>>1;
        if (L<=mid) Update(lc,L,R,val);
        if (mid<R) Update(rc,L,R,val);
        pushup(i);
    }
    int Query(int i,int L,int R){
        if (L<=tree[i].l&&tree[i].r<=R){
            return tree[i].val;
        }
        pushdown(i);
        int mid=(tree[i].l+tree[i].r)>>1,ans=0;
        if (L<=mid) ans+=Query(lc,L,R);
        if (mid<R) ans+=Query(rc,L,R);
        return ans;
    }
}
using namespace SegmentTree;
int main(){
    int n=read(),m=read();
    for (register int i=1;i<=n;++i){
        b[i]=read();
    }
    for (register int i=1;i<=n;++i){
        a[i]=b[i]-b[i-1];
    }
    Build(1,1,n);
    while (m--){
        int opr=read();
        if (opr==1){
            int l=read(),r=read(),k=read(),d=read();
            Update(1,l,l,k);
            if (l<r){
                Update(1,l+1,r,d);
            }
            if (r!=n) Update(1,r+1,r+1,-k-d*(r-l));
        }
        else if (opr==2){
            int p=read();
            printf("%d\n",Query(1,1,p));
        }
    }
}