P1438 无聊的数列

Jisoo

对于一个等差数列?

直接维护这个区间的首项和公差就可以了

最后的答案反正只有单点查询(区间也差不多)

返回那个小区间的“首项”就可以了

#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;
} 
posted @ 2021-09-27 11:41  Simex  阅读(22)  评论(0编辑  收藏  举报