【UOJ#164】清华集训2015V

QwQzcysky真是菜死了,这是我刚上高一的时候坤爷在夏令营讲的,可是今天才切掉……

想想也神奇,一个2016.11才学会线段树的菜鸡,夏令营的时候居然听过Segment-Tree-Beats?

所以我们来看下这个神奇的Segment-Tree-Beats.

我们维护一个神奇的标记二元组(x,y),在树点上打这个标记表示$val[o]=max(val[o]+x,y)$

然后我们看一下它是不是可以合并(否则这就是一个没有的东西)

merge:merge(Tag[x],Tag[y])=(x1+x2,max(y1+x2,y2))

那么我们怎么把操作对应到标记修改上呢?

  • opt1:(x,0)
  • opt2:(-x,0)
  • opt3:(-inf,x)

query的时候查询标记,正常pushdown就行了。

所以再维护一下历史最大值,这个对于做过一些简单的Segment-Tree-Beats的同学来说简直是简单的不行。

不过每次修改的时候有一个小细节,(x,y)的x最好是max(x,-inf),否则会出事。

#include<bits/stdc++.h>
#define N 500010
#define lson (o<<1)
#define rson (o<<1|1)
using namespace std;
typedef long long ll;
const ll inf=1e18;
int n,m;
struct Tag{
    ll x,y,tx,ty;
    Tag(ll x=0,ll y=0,ll tx=0,ll ty=0):x(x),y(y),tx(tx),ty(ty){}
};
ll a[N];
struct Segment_Tree_Beats{
    ll val[N<<2];Tag tag[N<<2];
    inline Tag merge(Tag a,Tag b){
        return Tag(max(a.x+b.x,-inf),max(a.y+b.x,b.y),max(a.tx,a.x+b.tx),max(a.ty,max(a.y+b.tx,b.ty)));
    }
    inline void pushdown(int o,int l,int r){
        if(l==r)return;
        tag[lson]=merge(tag[lson],tag[o]);
        tag[rson]=merge(tag[rson],tag[o]);
        tag[o]=Tag(0,0,0,0);
    }
    void build(int o,int l,int r){
        tag[o]=Tag(0,0,0,0);
        if(l==r)return;int mid=(l+r)>>1;
        build(lson,l,mid);build(rson,mid+1,r);
    }
    void change(int o,int l,int r,int ql,int qr,Tag v){
        if(ql<=l&&r<=qr){tag[o]=merge(tag[o],v);return;}
        int mid=(l+r)>>1;pushdown(o,l,r);
        if(ql<=mid)change(lson,l,mid,ql,qr,v);
        if(qr>mid)change(rson,mid+1,r,ql,qr,v);
    }
    Tag query(int o,int l,int r,int q){
        if(l==r)return tag[o];
        int mid=(l+r)>>1;pushdown(o,l,r);
        if(q<=mid)return query(lson,l,mid,q);
        else return query(rson,mid+1,r,q);
    }
}T;
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 main(){
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    T.build(1,1,n);
    while(m--){
        Tag ans;int opt=read();
        if(opt==1){
            int l=read(),r=read(),x=read();
            T.change(1,1,n,l,r,Tag(x,-inf,x,-inf));
        }
        if(opt==2){
            int l=read(),r=read(),x=read();
            T.change(1,1,n,l,r,Tag(-x,0,-x,0));
        }
        if(opt==3){
            int l=read(),r=read(),x=read();
            T.change(1,1,n,l,r,Tag(-inf,x,-inf,x));
        }
        if(opt==4){
            int x=read();ans=T.query(1,1,n,x);
            printf("%lld\n",max(a[x]+ans.x,ans.y));
        }
        if(opt==5){
            int x=read();ans=T.query(1,1,n,x);
            printf("%lld\n",max(a[x]+ans.tx,ans.ty));
        }
    }
}

 

posted @ 2017-06-13 09:28  zcysky  阅读(323)  评论(0编辑  收藏  举报