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\n",getmax(1,1,n,x,y));
                else printf("%lld\n",getsum(1,1,n,x,y));
            }
        }
    }
    
    return 0;
}

 

posted @ 2019-01-09 07:50  AKCqhzdy  阅读(149)  评论(0编辑  收藏  举报