zoukankan      html  css  js  c++  java
  • hdu5306 Gorgeous Sequence

    留了几天的坑终于填了。。。

    这个东西是线段树取区间最值问题。。。在吉司机16的论文里面。。。

    其实就是让修改值和区间次大比较,假如次大较小就可以只改最大值,维护一下就可以了

    注意到标记大小是按深度递增递增的

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    struct node
    {
        LL mx,mxc,sx,sum,md;
    }tr[2100000];int trlen,a[1100000];
    
    void update(int now)
    {
        int lc=now<<1,rc=now<<1|1;
        tr[now].sum=tr[lc].sum+tr[rc].sum;
        tr[now].mx=max(tr[lc].mx,tr[rc].mx);
        
        tr[now].mxc=0;
        if(tr[lc].mx==tr[now].mx)tr[now].mxc+=tr[lc].mxc;
        if(tr[rc].mx==tr[now].mx)tr[now].mxc+=tr[rc].mxc;
        
        tr[now].sx=max(tr[lc].sx,tr[rc].sx);
        if(tr[lc].mx!=tr[rc].mx)
            tr[now].sx=max(tr[now].sx,min(tr[lc].mx,tr[rc].mx));
    }
    void pushdown(int now)
    {
        if(tr[now].md!=0)
        {
            int lc=now<<1,rc=now<<1|1;
            if(tr[lc].mx>tr[now].md)
            {
                tr[lc].sum-=tr[lc].mxc*(tr[lc].mx-tr[now].mx);
                tr[lc].mx=tr[lc].md=tr[now].md;
            }
            if(tr[rc].mx>tr[now].md)
            {
                tr[rc].sum-=tr[rc].mxc*(tr[rc].mx-tr[now].mx);
                tr[rc].mx=tr[rc].md=tr[now].md;
            }
        }
    }
    //~~~~~~~~~~~~~~tool~~~~~~~~~~~~~~~~~~~~~~~~~
    
    void bt(int now,int ql,int qr)
    {
        if(ql==qr)
        {
            tr[now].mx=tr[now].sum=a[ql];
            tr[now].mxc=1;
            tr[now].sx=-1;
        }
        else
        {
            int mid=(ql+qr)/2;
            int lc=now<<1,rc=now<<1|1;
            bt(lc,ql,mid),bt(rc,mid+1,qr);
            update(now);
        }
        tr[now].md=0;
    }
    void change(int now,int ql,int qr,int l,int r,LL k)
    {
        if(tr[now].mx<=k)return ;
        if(ql==qr){tr[now].mx=tr[now].sum=k;return ;}
        int mid=(ql+qr)/2;
        int lc=now<<1,rc=now<<1|1;
        
        if(ql==l&&qr==r)
        {
            if(tr[now].sx<k)
            {
                tr[now].sum-=tr[now].mxc*(tr[now].mx-k);
                tr[now].mx=tr[now].md=k;
                return ;
            }
            else 
            {
                change(lc,ql,mid,l,mid,k),change(rc,mid+1,qr,mid+1,r,k);
                update(now);
            }
        }
        else
        {
            pushdown(now);
                 if(r<=mid)  change(lc,ql,mid,l,r,k);
            else if(mid+1<=l)change(rc,mid+1,qr,l,r,k);
            else change(lc,ql,mid,l,mid,k),change(rc,mid+1,qr,mid+1,r,k);
            update(now);
        }
    }
    //~~~~~~~~~~~~~~~~~~~~~~change~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    LL getmax(int now,int ql,int qr,int l,int r)
    {
        if(ql==l&&qr==r)return tr[now].mx;
        
        int mid=(ql+qr)/2;
        int lc=now<<1,rc=now<<1|1;
        pushdown(now);
        
             if(r<=mid)  return getmax(lc,ql,mid,l,r);
        else if(mid+1<=l)return getmax(rc,mid+1,qr,l,r);
        else return max(getmax(lc,ql,mid,l,mid),getmax(rc,mid+1,qr,mid+1,r));
    }
    LL getsum(int now,int ql,int qr,int l,int r)
    {
        if(ql==l&&qr==r)return tr[now].sum;
        
        int mid=(ql+qr)/2;
        int lc=now<<1,rc=now<<1|1;
        pushdown(now);
        
             if(r<=mid)  return getsum(lc,ql,mid,l,r);
        else if(mid+1<=l)return getsum(rc,mid+1,qr,l,r);
        else return getsum(lc,ql,mid,l,mid)+getsum(rc,mid+1,qr,mid+1,r);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~solve~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
            trlen=0;bt(1,1,n);
            
            int op,x,y;LL d;
            while(m--)
            {
                scanf("%d",&op);
                if(op==0)
                {
                    scanf("%d%d%lld",&x,&y,&d);
                    change(1,1,n,x,y,d);
                }
                else
                {
                    scanf("%d%d",&x,&y);
                    if(op==1)printf("%lld
    ",getmax(1,1,n,x,y));
                    else printf("%lld
    ",getsum(1,1,n,x,y));
                }
            }
        }
        
        return 0;
    }
  • 相关阅读:
    select和epoll原理和区别
    linux网络编程中的基本概念
    linux 基本概念
    进程与线程(1)- 基本概念
    CI持续集成
    git基本操作(入门)
    pytest特色与实用插件
    使用pabot并行执行robotframework用例
    如何编写测试用例
    前端_vue-cli+element-ui+AceEditor+codemirror+electron-vue
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10242335.html
Copyright © 2011-2022 走看看