• HDU 5306Gorgeous Sequence (吉司机线段树)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5306

    题目大意:给你n个数,你有3种操作,操作如下:

    $0,x,y,v$,对区间$a[x]-a[y]$取$min(v,a[i])$

    $1,x,y$,询问区间最大值

    $2,x,y$,询问区间和

    Sample Input

    1
    5 5
    1 2 3 4 5
    1 1 5
    2 1 5
    0 3 5 3
    1 1 5
    2 1 5

    Sample Output

    5
    15
    3
    12

    吉司机线段树,通常就是比正常的线段树多维护了个次的东西,比若说这题,我们可以维护一个次大值,如果该区间的最大值小于修改的v,那么直接return,如果大于次大值,那么也就是说只有最大值需要修改,那么我们记录一下最大值的个数,修改的时候我们直接对sum+(最大值-val)乘上最大值的数量就好了,然后将该区间的最大值修改为val,然后开始push_down了,如下所示:

    void solve(int rt,int val)
    {
        if (val>=tree[rt].mx) return;
        tree[rt].sum+=1LL*(val-tree[rt].mx)*tree[rt].mxnb;
        tree[rt].mx=val;
    }
    
    void push_down(int rt)
    {
        solve(lc,tree[rt].mx);solve(rc,tree[rt].mx);
    }
    
    void update(int l,int r,int rt,int L,int R,int val)
    {
        if (val>=tree[rt].mx) return;
        if (l>=L && r<=R && val>tree[rt].cimx){
            solve(rt,val);
            return;
        }
        int mid=(l+r)>>1; 
        push_down(rt);
        if (mid>=L) update(lson,L,R,val);
        if (mid<R) update(rson,L,R,val);
        push_up(rt);
    }

    这样看起来似乎复杂度还是有点高,但对于随机数据来讲,他的平均复杂度还是不错的

    以下是AC代码:

    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define lc rt<<1
    #define rc rt<<1|1
    typedef long long ll;
    const int mac=1e6+10;
    
    struct node
    {
        int mx,cimx,mxnb;
        ll sum;
    }tree[mac<<2];
    
    void push_up(int rt)
    {
        tree[rt].sum=tree[lc].sum+tree[rc].sum;
        if (tree[lc].mx==tree[rc].mx){
            tree[rt].mx=tree[lc].mx;
            tree[rt].mxnb=tree[lc].mxnb+tree[rc].mxnb;
            tree[rt].cimx=max(tree[lc].cimx,tree[rc].cimx);
        }
        else {
            if (tree[lc].mx>tree[rc].mx) {
                tree[rt].mxnb=tree[lc].mxnb;
                tree[rt].cimx=max(tree[rc].mx,tree[lc].cimx);
            }
            else {
                tree[rt].mxnb=tree[rc].mxnb;
                tree[rt].cimx=max(tree[lc].mx,tree[rc].cimx);
            }
            tree[rt].mx=max(tree[lc].mx,tree[rc].mx);
        }
    }
    
    void solve(int rt,int val)
    {
        if (val>=tree[rt].mx) return;
        tree[rt].sum+=1LL*(val-tree[rt].mx)*tree[rt].mxnb;
        tree[rt].mx=val;
    }
    
    void push_down(int rt)
    {
        solve(lc,tree[rt].mx);solve(rc,tree[rt].mx);
    }
    
    void build(int l,int r,int rt)
    {
        tree[rt].cimx=-1;
        if (l==r){
            int x;
            scanf ("%d",&x);
            tree[rt].mx=tree[rt].sum=x;
            tree[rt].mxnb=1;
            return;
        }
        int mid=(l+r)>>1;
        build(lson);build(rson);
        push_up(rt);
    }
    
    void update(int l,int r,int rt,int L,int R,int val)
    {
        if (val>=tree[rt].mx) return;
        if (l>=L && r<=R && val>tree[rt].cimx){
            solve(rt,val);
            return;
        }
        int mid=(l+r)>>1; 
        push_down(rt);
        if (mid>=L) update(lson,L,R,val);
        if (mid<R) update(rson,L,R,val);
        push_up(rt);
    }
    
    ll query(int l,int r,int rt,int L,int R,int id)
    {
        ll ans=0;
        if (l>=L && r<=R) {
            if (!id) return 1LL*tree[rt].mx;
            else return tree[rt].sum;
        }
        push_down(rt);
        int mid=(l+r)>>1;
        if (mid>=L) {
            if (!id) ans=max(ans,query(lson,L,R,id));
            else ans+=query(lson,L,R,id);
        }
        if (mid<R) {
            if (!id) ans=max(ans,query(rson,L,R,id));
            else ans+=query(rson,L,R,id);
        }
        return ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int t;
        scanf ("%d",&t);
        while (t--){
            int n,q;
            scanf ("%d%d",&n,&q);
            build(1,n,1);
            while (q--){
                int opt,l,r,v;
                scanf ("%d%d%d",&opt,&l,&r);
                if (!opt) {
                    scanf ("%d",&v);
                    update(1,n,1,l,r,v);
                }
                else if (opt==1) printf("%lld
    ",query(1,n,1,l,r,0));
                else printf("%lld
    ",query(1,n,1,l,r,1));
            }
        }
        return 0;
    }
    路漫漫兮
  • 相关阅读:
    IO和序列化
    委托与事件
    [基础不过关填坑] 跨iframe触发事件
    有哪些新手程序员不知道的小技巧?
    给echarts加个“全屏展示”
    bootstrapTable使用场景及方式
    bootstrap datetimepicker 格式化yyyymmdd时,无法读取yyyymmdd格式
    【变态需求】bootstrapTable列排序-选择正序倒序不排序
    myeclipse、maven、tomcat、jdk技巧和坑【待完善】
    【调试技巧】 Fiddler高级用法之url映射请求
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13275773.html
Copyright © 2020-2023  润新知