HDU - 5306 - Gorgeous Sequence - 模板 - 势能线段树(吉司机线段树)

吉司机线段树用于维护区间[l,r]对x取最小值,区间查询最小值和区间求和.

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

const int N = 1e6+10;

struct node{
    int l,r;
    ll mx;
    ll se;
    int cnt;
    ll sum;
};

ll arr[N];
node tr[N<<2];

void pushdown(int rt){
    if(tr[rt<<1].mx > tr[rt].mx){
        tr[rt<<1].sum -= (tr[rt<<1].mx-tr[rt].mx)*tr[rt<<1].cnt; //左儿子的最大值小于父结点的最大值,就把左儿子的最大值替换为父结点的最大值
        tr[rt<<1].mx = tr[rt].mx;
    }

    if(tr[rt<<1|1].mx > tr[rt].mx){
        tr[rt<<1|1].sum -= (tr[rt<<1|1].mx-tr[rt].mx)*tr[rt<<1|1].cnt;
        tr[rt<<1|1].mx = tr[rt].mx;
    }
}

void pushup(int rt){
    tr[rt].sum = tr[rt<<1].sum + tr[rt<<1|1].sum;
    tr[rt].mx = max(tr[rt<<1].mx,tr[rt<<1|1].mx);
    tr[rt].cnt = 0;

    if(tr[rt<<1].mx == tr[rt<<1|1].mx){
        tr[rt].cnt = tr[rt<<1].cnt + tr[rt<<1|1].cnt;
        tr[rt].se = max(tr[rt<<1].se,tr[rt<<1|1].se);
    }else{
        if(tr[rt<<1].mx > tr[rt<<1|1].mx){
            tr[rt].cnt = tr[rt<<1].cnt;
            tr[rt].se = max(tr[rt<<1].se,tr[rt<<1|1].mx);
        }else{
            tr[rt].cnt = tr[rt<<1|1].cnt;
            tr[rt].se = max(tr[rt<<1].mx,tr[rt<<1|1].se);
        }
    }
}


void build(int rt,int l,int r){
    if(l==r){
        tr[rt]={l,r,arr[l],-1,1,arr[l]};
    }else{
        int mid=l+r>>1;
        tr[rt]={l,r};
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
}

void modify(int rt,int l,int r,int x){
    if(tr[rt].mx <= x){
        return;
    }

    if(l <= tr[rt].l && r >= tr[rt].r && tr[rt].se < x){
        tr[rt].sum -= (tr[rt].mx - x)*tr[rt].cnt;
        tr[rt].mx = x;
        return;
    }

    pushdown(rt);
    int mid = tr[rt].l + tr[rt].r >> 1;
    if(l <= mid){
        modify(rt<<1,l,r,x);
    }

    if(r > mid){
        modify(rt<<1|1,l,r,x);
    }

    pushup(rt);
}


ll query_max(int rt,int l,int r){
    if(l <= tr[rt].l && r >= tr[rt].r){
        return tr[rt].mx;
    }else{
        pushdown(rt);
        int mid =tr[rt].l+tr[rt].r >>1;
        ll res = 0;
        if(l <= mid) res = query_max(rt<<1,l,r);
        if(r > mid) res = max(res,query_max(rt<<1|1,l,r));
        return res;
    }
}


ll query_sum(int rt,int l,int r){
    if(l <= tr[rt].l && r >= tr[rt].r){
        return tr[rt].sum;
    }else{
        pushdown(rt);
        int mid = tr[rt].l+tr[rt].r >>1;
        ll res =0;
        if(l <= mid) res += query_sum(rt<<1,l,r);
        if(r > mid) res += query_sum(rt<<1|1,l,r);
        return res;
    }
}
int main(){
    int t,n,q,cmd,x,y,v;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&q);
        for(int i = 1; i <= n; i++){
            scanf("%lld",&arr[i]);
        }
        build(1,1,n);
        while(q--){
            scanf("%d",&cmd);
            switch (cmd){
            case 0:
                scanf("%d%d%d",&x,&y,&v);
                modify(1,x,y,v);
                break;
            case 1:
                scanf("%d%d",&x,&y);
                printf("%d\n",query_max(1,x,y));
                break;
            default:
                scanf("%d%d%",&x,&y);
                printf("%lld\n",query_sum(1,x,y));
            }
        }
    }

    system("pause");
    return 0;
}
posted @ 2020-11-18 17:45  popozyl  阅读(94)  评论(0编辑  收藏  举报