P1438

· · 题解

我太弱了,根本看不懂大佬们的差分式的的思路,就只好用一种复杂的方法来写。

但仍是线段树!

我设了三个数组,分别用来表示rt管辖的区间的第一个数,这个区间被加上的等差数列(还没向下传给他的儿子们)的首项,以及公差。 主要注意下rt<<1和rt<<1|1的区别就行了。

上代码

//1438
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=100000+5;
int first[maxn<<2],one[maxn<<2],tol[maxn<<2],bj[maxn<<2];
int a[maxn];
int ans=0;
void pushup(int rt)
{
    first[rt]=first[rt<<1];
}
void build(int rt,int l,int r)
{
    if(l==r)
    {
        first[rt]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void pushdown(int rt,int l,int r)
{
    int mid=(l+r)>>1;
    first[rt<<1]=first[rt];
    first[rt<<1|1]+=(one[rt]+(mid+1-l)*tol[rt]);
    one[rt<<1]+=one[rt];
    tol[rt<<1]+=tol[rt];
    one[rt<<1|1]+=(one[rt]+tol[rt]*(mid+1-l));
    tol[rt<<1|1]+=tol[rt];
    tol[rt]=0;
    one[rt]=0;
}
void update(int rt,int l,int r,int L,int R,int del,int k)
{
    if(l>R||r<L)return;
    if(L<=l&&r<=R)
    {
        first[rt]+=(k+del*(l-L));
        tol[rt]+=del;
        one[rt]+=(k+del*(l-L));
        return;
    }
    int mid=(l+r)>>1;
    pushdown(rt,l,r);
    update(rt<<1,l,mid,L,R,del,k);
    update(rt<<1|1,mid+1,r,L,R,del,k);
    pushup(rt);
}
void query(int rt,int l,int r,int L,int R,int k)
{
    if(l>R||r<L)return;
    if(L<=l&&r<=R)
    {
        ans=first[rt];
        return;
    }
    int mid=(l+r)>>1;
    pushdown(rt,l,r);
    query(rt<<1,l,mid,L,R,k);
    query(rt<<1|1,mid+1,r,L,R,k);
    pushup(rt);
}
int main()
{
    //freopen("1438.in","r",stdin); freopen("out.txt","w",stdout);
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    build(1,1,n);
    int order,l,r,del,k;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&order);
        if(order==1)
        {
            scanf("%d%d%d%d",&l,&r,&k,&del);
            update(1,1,n,l,r,del,k);
        }
        else
        {
            ans=0;
            int p;
            scanf("%d",&p);
            query(1,1,n,p,p,k);
            printf("%d\n",ans);
        }
    }
    return 0;
}