模板吉司机线段树 HDU 5306 Gorgeous Sequence

Posted white-star

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板吉司机线段树 HDU 5306 Gorgeous Sequence相关的知识,希望对你有一定的参考价值。

也叫小清新线段树,用于解决区间最值修改问题

具体可以参考jiry_2神犇的集训队论文和WC2016上的PPT

此题就作为模板好了,模板的话写法是比较精妙的

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define int long long

const int N=1000000+10;

int n,m,a[N];
struct tree//其实更新标记和最大值可以二合一
//若更新成功则最大值就是标记,若没有更新下传最大值也不会更新子区间 
    int l,r,mx,se,c,sum;
    #define l(i) t[i].l
    #define r(i) t[i].r
    #define c(i) t[i].c
    #define mx(i) t[i].mx
    #define se(i) t[i].se
    #define sum(i) t[i].sum
    #define ls rt<<1
    #define rs rt<<1|1
t[N<<2];

template<typename T>void read(T &x)
    x=0;char c=getchar(),f=1;
    while(!isdigit(c)) if(c=='-') f=-1; c=getchar(); 
    while(isdigit(c)) x=x*10+c-'0'; c=getchar(); 
    x*=f;


void push_up(int rt)
    sum(rt)=sum(ls)+sum(rs);
    mx(rt)=max(mx(ls),mx(rs));
    se(rt)=max(se(ls),se(rs));
    if(mx(ls)!=mx(rs)) se(rt)=max(se(rt),min(mx(ls),mx(rs)));
    if(mx(rt)==mx(ls)) c(rt)+=c(ls);
    if(mx(rt)==mx(rs)) c(rt)+=c(rs);
    //注意啦,此处写法十分精妙。
    //若mx(ls)==mx(rs) c(rt)=c(ls)+c(rs) 


void update(int rt,int z)//在下传标记时z不可能<=se(rt),因为Z>se(rt的祖先节点)>=se(rt)
    if(z>=mx(rt)) return;
    sum(rt)-=(mx(rt)-z)*c(rt);
    mx(rt)=z;


void build(int rt,int l,int r)
    l(rt)=l,r(rt)=r;
    if(l==r)
        mx(rt)=sum(rt)=a[l],se(rt)=-1;
        c(rt)=1;
        return;
    
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    push_up(rt);


void push_down(int rt)
    update(ls,mx(rt)),update(rs,mx(rt));


void change(int rt,int x,int y,int z)
    if(z>=mx(rt)) return;//剪枝,如果比大区间的最大值还大,自然不可能修改小区间 
    if(l(rt)>=x&&r(rt)<=y&&z>se(rt))
        update(rt,z);
        return;
    
    int mid=l(rt)+r(rt)>>1;
    push_down(rt);
    if(x<=mid) change(ls,x,y,z);
    if(y>mid) change(rs,x,y,z);
    push_up(rt);


int getmax(int rt,int x,int y)
    if(l(rt)>=x&&r(rt)<=y) return mx(rt);
    push_down(rt);
    int ans=0;
    int mid=l(rt)+r(rt)>>1;
    if(x<=mid) ans=max(ans,getmax(ls,x,y));
    if(y>mid) ans=max(ans,getmax(rs,x,y));
    return ans;


int getsum(int rt,int x,int y)
    if(l(rt)>=x&&r(rt)<=y) return sum(rt);
    push_down(rt);
    int ans=0,mid=l(rt)+r(rt)>>1;
    if(x<=mid) ans+=getsum(ls,x,y);
    if(y>mid) ans+=getsum(rs,x,y);
    return ans;


void work()
    read(n),read(m);
    go(i,1,n) read(a[i]);
    build(1,1,n);
    int op,x,y,z;
    while(m--)
        read(op),read(x),read(y);
        if(!op) read(z),change(1,x,y,z);
        else if(op==1) printf("%lld\n",getmax(1,x,y));
        else if(op==2) printf("%lld\n",getsum(1,x,y));
    


signed main()
    //freopen("data.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;read(T);
    while(T--) work();
    return 0;

以上是关于模板吉司机线段树 HDU 5306 Gorgeous Sequence的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5306 Gorgeous Sequence

hdu5306 Gorgeous Sequence

hdu6521 吉司机线段树

HDU4695 最假女选手(吉司机线段树)

数据结构吉司机线段树

Gorgeous Sequence (hdu 5306) (线段树)