luogu 1438無聊的數列 線段樹區間修改區間求和

題意,n(1e5)個數,m(1e5)個操作,第一種將[L,R]範圍內的數分別加上首項爲K,公差爲D的等差數列,第二種詢問[L,R]範圍內區間和

維護差分數組,每次修改時,sun[l]+=k;(l,R]:sum[i]+=D;sum[R+1]-=(K+(R-L)*D);

#include<bits/stdc++.h>
#define ls root<<1,l,mid
#define rs root<<1|1,mid+1,r
#define MAXN 100001

using namespace std;

int n,m;
int s[MAXN],sum[MAXN<<2],lazy[MAXN<<2];

inline void push_up(int root)
{
    sum[root]=sum[root<<1]+sum[root<<1|1];
}

inline void push_down(int root,int len)
{
    if(lazy[root])
    {
        lazy[root<<1]+=lazy[root];
        lazy[root<<1|1]+=lazy[root];
        sum[root<<1]+=(len-(len>>1))*lazy[root];
        sum[root<<1|1]+=(len>>1)*lazy[root];
        lazy[root]=0;
    }
}

inline void update(int root,int l,int r,int L,int R,int val)
{
    if(L<=l && r<=R){sum[root]+=(r-l+1)*val;lazy[root]+=val;return;}
    push_down(root,r-l+1);
    int mid=(l+r)>>1;
    if(mid>=L) update(ls,L,R,val);
    if(mid<R) update(rs,L,R,val);
    push_up(root);
}

inline int query(int root,int l,int r,int L,int R)
{
    if(L<=l && r<=R) return sum[root];
    push_down(root,r-l+1);
    int mid=(l+r)>>1;int total=0;
    if(mid>=L) total+=query(ls,L,R);
    if(mid<R) total+=query(rs,L,R);
    return total;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>s[i];
    int type,L,R,K,D,ask;
    while(m--)
    {
        cin>>type;
        if(type==1)
        {
            cin>>L>>R>>K>>D;
            update(1,1,n,L,L,K);
            if(R>L) update(1,1,n,L+1,R,D);
            int N=R-L+1;
            if(R!=n) update(1,1,n,R+1,R+1,-(K+(N-1)*D));
        }
        else
        {
            cin>>ask;
            printf("%d\n",s[ask]+query(1,1,n,1,ask));
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章