BZOJ4355:Play with sequence(吉司机线段树)

传送门

题解:
原来的赋值操作相当于加上 − ∞ 之后 chkmax c h k m a x
注意到给的数据保证0肯定作为最小值出现,相当于要维护加和 chkmax c h k m a x 和支持查询最小值个数的线段树,这明显是吉司机线段树。

同时维护 add,chkmax a d d , c h k m a x 只需要保证 add a d d chkmax c h k m a x 先下传,如果在 chkmax c h k m a x add a d d ,把 chkmax c h k m a x tag t a g 加上 add a d d 的值即可。

#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
const LL INF=(0x3f3f3f3f)*200ll;
inline int rd() {
    char ch=getchar(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
    return i*f;
}

inline void W(LL x) {
    static int buf[50];
    if(!x) {putchar('0'); return;}
    if(x<0) {putchar('-'); x=-x;}
    while(x) {buf[++buf[0]]=x%10; x/=10;}
    while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}

const int N=3e5+50;

int n,m;
LL mn[N*4],se[N*4],mnc[N*4],atag[N*4],ctag[N*4];

inline void upt(int k) {
    int lc=k<<1,rc=lc|1;
    if(mn[lc]==mn[rc]) {
        mn[k]=mn[lc];
        mnc[k]=mnc[lc]+mnc[rc];
        se[k]=min(se[lc],se[rc]);
    } else {
        if(mn[lc]>mn[rc]) swap(lc,rc);
        mn[k]=mn[lc]; mnc[k]=mnc[lc];
        se[k]=min(se[lc],mn[rc]);
    }
}

inline void build(int k,int l,int r) {
    atag[k]=0; ctag[k]=-INF;
    if(l==r) {
        mn[k]=rd(); se[k]=0x3f3f3f3f3f3f3f3f;
        mnc[k]=1;
        return;
    } int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    upt(k);
}
inline void add(int k,int l,int r,LL v) {
    if(ctag[k]!=-INF) ctag[k]+=v;
    mn[k]+=v; se[k]+=v; atag[k]+=v;
}

inline void color(int k,int l,int r,LL v) {
    if(mn[k]>=v) return;
    if(ctag[k]>=v) return;
    int mid=(l+r)>>1;
    if((l!=r) && atag[k]) {
        add(k<<1,l,mid,atag[k]);
        add(k<<1|1,mid+1,r,atag[k]);
        atag[k]=0;
    }
    if(se[k]>v) {
        ctag[k]=v; mn[k]=v;
    } else {
        ctag[k]=-INF;
        color(k<<1,l,mid,v);
        color(k<<1|1,mid+1,r,v);
        upt(k);
    }
}

inline void pushdown(int k,int l,int r) {
    int mid=(l+r)>>1;
    if(atag[k]) {
        add(k<<1,l,mid,atag[k]);
        add(k<<1|1,mid+1,r,atag[k]);
        atag[k]=0;
    }
    if(ctag[k]!=-INF) {
        color(k<<1,l,mid,ctag[k]);
        color(k<<1|1,mid+1,r,ctag[k]);
        ctag[k]=-INF;
    }
}

inline void modify1(int k,int l,int r,int L,int R,LL v) {
    if(L<=l&&r<=R) {add(k,l,r,v); return;}
    pushdown(k,l,r); int mid=(l+r)>>1;
    if(R<=mid) modify1(k<<1,l,mid,L,R,v);
    else if(L>mid) modify1(k<<1|1,mid+1,r,L,R,v);
    else modify1(k<<1,l,mid,L,R,v),modify1(k<<1|1,mid+1,r,L,R,v);
    upt(k);
}

inline void modify2(int k,int l,int r,int L,int R,LL v) {
    if(L<=l&&r<=R) {color(k,l,r,v); return;}
    pushdown(k,l,r); int mid=(l+r)>>1;
    if(R<=mid) modify2(k<<1,l,mid,L,R,v);
    else if(L>mid) modify2(k<<1|1,mid+1,r,L,R,v);
    else modify2(k<<1,l,mid,L,R,v),modify2(k<<1|1,mid+1,r,L,R,v);
    upt(k);
}

inline int query(int k,int l,int r,int L,int R) {
    if(L<=l&&r<=R) {return (!mn[k])*mnc[k];}
    pushdown(k,l,r); int mid=(l+r)>>1;
    if(R<=mid) return query(k<<1,l,mid,L,R);
    else if(L>mid) return query(k<<1|1,mid+1,r,L,R);
    else return query(k<<1,l,mid,L,R)+query(k<<1|1,mid+1,r,L,R);
}

int main() {
    n=rd(), m=rd();
    build(1,1,n);
    while(m--) {
        int op=rd(),l=rd(),r=rd();
        if(op==1) {
            modify1(1,1,n,l,r,-INF);
            modify2(1,1,n,l,r,rd());
        } else if(op==2) {
            modify1(1,1,n,l,r,rd());
            modify2(1,1,n,l,r,0);
        } else {W(query(1,1,n,l,r)); putchar('\n');}
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值