【UOJ#169】元旦老人与数列

论文题。

考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记。

我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值。

对于被覆盖一半的区间,讨论一下即可。

对于每个最小值和次小值记录前缀最小值,当前/历史最小值,当到达合法区间的时候:

如果区间最小值>x,直接退出。

如果minv[o]<x<semn[o],那么更新当前的次小值

反之继续向下。

#include<bits/stdc++.h>
const int inf=2e9+7;
const int N=500005;
using namespace std;
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int n,m;
struct Segment_Tree_Beats{
#define lson (o<<1)
#define rson (o<<1|1)
    int his[N<<2],pra[N<<2],prb[N<<2],a[N<<2],b[N<<2],minv[N<<2],semn[N<<2];
    inline void pushup(int o){
        if(minv[lson]==minv[rson])minv[o]=minv[lson],semn[o]=min(semn[lson],semn[rson]);
        else if(minv[lson]<minv[rson]){minv[o]=minv[lson];semn[o]=min(semn[lson],minv[rson]);}
        else{minv[o]=minv[rson];semn[o]=min(semn[rson],minv[lson]);}
        his[o]=min(his[lson],his[rson]);
    }
    inline void puttag(int o,int v){
        his[o]=min(his[o],minv[o]+v);
        a[o]+=v;b[o]+=v;minv[o]+=v;semn[o]+=v;semn[o]=min(semn[o],inf);
        pra[o]=min(pra[o],a[o]);
        prb[o]=min(prb[o],b[o]);
    }
    inline void plus(int o,int ax,int pa,int bx,int pb){
        his[o]=min(his[o],minv[o]+pa);
        pra[o]=min(pra[o],pa+a[o]);
        prb[o]=min(prb[o],pb+b[o]);
        a[o]+=ax;b[o]+=bx;minv[o]+=ax;semn[o]+=bx;semn[o]=min(semn[o],inf);
    }
    inline void pushdown(int o){
        int mmmm=min(minv[lson],minv[rson]);
        if(minv[lson]==mmmm)plus(lson,a[o],pra[o],b[o],prb[o]);else plus(lson,b[o],prb[o],b[o],prb[o]);
        if(minv[rson]==mmmm)plus(rson,a[o],pra[o],b[o],prb[o]);else plus(rson,b[o],prb[o],b[o],prb[o]);
        a[o]=b[o]=pra[o]=prb[o]=0;
    }
    inline void build(int o,int l,int r){
        if(l==r){
            minv[o]=read();his[o]=minv[o];semn[o]=inf;
            return;
        }
        int mid=(l+r)>>1;
        build(lson,l,mid);build(rson,mid+1,r);
        pushup(o);
    }
    inline void optadd(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr){puttag(o,v);return;}
        int mid=(l+r)>>1;pushdown(o);
        if(ql<=mid)optadd(lson,l,mid,ql,qr,v);
        if(qr>mid)optadd(rson,mid+1,r,ql,qr,v);
        pushup(o);
    }
    inline void dfs(int o,int l,int r,int v){
        if(minv[o]>=v)return;
        if(semn[o]>v){
            v-=minv[o];his[o]=min(his[o],minv[o]+v);
            pra[o]=min(pra[o],a[o]+v);
            a[o]+=v;minv[o]+=v;return;
        }
        int mid=(l+r)>>1;pushdown(o);
        dfs(lson,l,mid,v);dfs(rson,mid+1,r,v);
        pushup(o);
    }
    inline void change(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr){dfs(o,l,r,v);return;}
        int mid=(l+r)>>1;pushdown(o);
        if(ql<=mid)change(lson,l,mid,ql,qr,v);
        if(qr>mid)change(rson,mid+1,r,ql,qr,v);
        pushup(o);
    }
    inline int querynow(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return minv[o];
        int mid=(l+r)>>1,ans=inf;pushdown(o);
        if(ql<=mid)ans=min(ans,querynow(lson,l,mid,ql,qr));
        if(qr>mid)ans=min(ans,querynow(rson,mid+1,r,ql,qr));
        return ans;
    }
    inline int queryhis(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return his[o];
        int mid=(l+r)>>1,ans=inf;pushdown(o);
        if(ql<=mid)ans=min(ans,queryhis(lson,l,mid,ql,qr));
        if(qr>mid)ans=min(ans,queryhis(rson,mid+1,r,ql,qr));
        return ans;
    }
}T;
int main(){
    n=read();m=read();
    T.build(1,1,n);
    while(m--){
        int opt=read(),l=read(),r=read();
        if(opt==1){int x=read();T.optadd(1,1,n,l,r,x);}
        if(opt==2){int x=read();T.change(1,1,n,l,r,x);}
        if(opt==3)printf("%d\n",T.querynow(1,1,n,l,r));
        if(opt==4)printf("%d\n",T.queryhis(1,1,n,l,r));
    }
}

 

posted @ 2017-08-18 22:09  zcysky  阅读(390)  评论(0编辑  收藏  举报