CF438D The Child and Sequence

CF438D The Child and Sequence

 

给定数列,区间查询和,区间取模,单点修改。

n,m小于10^5

 

难点在于区间取模,类似于区间开方,如果这个区间的最大值$<=$ $mod$,不对其进行操作,反之对区间里每个数进行操作(由于操作数很少)

 

开$long long$

#include<bits/stdc++.h>

#define N 1000000
#define LL long long
using namespace std;

struct node{
    LL l,r,w,f,maxn;
}tr[N];

void push_up(LL k){
    tr[k].maxn=max(tr[k<<1].maxn,tr[k<<1|1].maxn);
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
}

void build(LL k,LL l,LL r){
    tr[k].l=l,tr[k].r=r;
    if(l==r){
        scanf("%d",&tr[k].w);
        tr[k].maxn=tr[k].w;
        return;
    }
    LL mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    push_up(k);
}

void push_down(LL k){
    if(tr[k].f){
        tr[k<<1].w+=tr[k].f*(tr[k<<1].r-tr[k<<1].l+1);
        tr[k<<1].f+=tr[k].f,tr[k<<1].maxn+tr[k].f;
        
        tr[k<<1|1].w+=tr[k].f*(tr[k<<1|1].r-tr[k<<1|1].l+1);
        tr[k<<1|1].f+=tr[k].f,tr[k<<1|1].maxn+tr[k].f;
        tr[k].f=0;
    }
}

void change(LL k,LL ql,LL qr,LL Mod,LL x){
    LL l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    if(l==r){
        if(!Mod) tr[k].w=tr[k].maxn=x;
        else tr[k].w%=Mod,tr[k].maxn=tr[k].w;
        return;
    }push_down(k);
    if(ql<=mid&&tr[k<<1].maxn>=Mod) change(k<<1,ql,qr,Mod,x);
    if(qr>mid&&tr[k<<1|1].maxn>=Mod) change(k<<1|1,ql,qr,Mod,x);
    push_up(k);
}

LL query(LL k,LL ql,LL qr){
    LL l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    if(ql<=l&&qr>=r) return tr[k].w;
    push_down(k);
    LL ans=0;
    if(ql<=mid) ans+=query(k<<1,ql,qr);
    if(qr>mid) ans+=query(k<<1|1,ql,qr);
    push_up(k);
    return ans;
}

LL n,m;


int main()
{
    scanf("%lld%lld",&n,&m);
    build(1,1,n);
    for(LL opt,l,r,x,i=1;i<=m;i++){
        scanf("%lld%lld%lld",&opt,&l,&r);
        if(opt==1){
            printf("%lld\n",query(1,l,r));
        }else if(opt==2){
            scanf("%lld",&x);
            change(1,l,r,x,0);
        }else if(opt==3){
            change(1,l,l,0,r);
        }
    }
    
    return 0;
}

 

posted @ 2018-10-22 16:59  清风我已逝  阅读(316)  评论(0编辑  收藏  举报