LA3938 RAY, Pass me the dishes (动态最大连续和)

。。。。。。
给出长度为n的整数序列,然后m次询问,对于每次询问,要求找到区间内的两个下标x,y使得区间和尽量大,如果有多解,x尽量小,还有多解,那么y也尽量小
 
思路:
线段树,建树过程中要标记
max_all:最大连续和
max_prefix:最大前缀和
max_suffix:最大后缀和
pre_r:最大前缀的结束位置
suf_l:最大后缀的开始位置
sum:区间总和
 
对于更新,由于要x尽量小与y尽量小,所以在更新的时候我们要确定好更新的顺序,也就是l先尽量小,然后才是y尽量小
更新有5种状况,那么按顺序就是
 
1.左边的sum+右区间的max_prefix;
2.左区间max_all
3.左边的max_suffix+右边的max_prefix
4.左边的max_suffix+右边的sum

5.右边的max_all

#include <iostream>
#include <stdio.h>


using namespace std;

#define lson 2*i
#define rson 2*i+1
#define LS l,mid,lson
#define RS mid+1,r,rson

#define LL long long
#define N 500005


LL s[N];
int n,m;
struct node
{
    int l,r,pre_r,suf_l;
    LL max_all,max_prefix,max_suffix,sum;
} a[N<<2];

void pushup(int l,int r,int i)
{
    int mid = (l+r)/2;
    a[i].sum = a[lson].sum+a[rson].sum;

    a[i].max_prefix = a[lson].max_prefix;
    a[i].pre_r = a[lson].pre_r;
    a[i].max_suffix = a[rson].max_suffix;
    a[i].suf_l = a[rson].suf_l;
//1.左边的sum+右区间的max_prefix;
    a[i].max_all = a[lson].sum+a[rson].max_prefix;
    a[i].l = l;
    a[i].r = a[rson].pre_r;
//2.左区间max_all
    if(a[i].max_all<a[lson].max_all || (a[i].max_all==a[lson].max_all&&a[i].l==a[lson].l))
    {
        a[i].max_all = a[lson].max_all;
        a[i].l = a[lson].l;
        a[i].r = a[lson].r;
    }
//3.左边的max_suffix+右边的max_prefix
    if(a[i].max_all<a[lson].max_suffix+a[rson].max_prefix || (a[i].max_all==a[lson].max_suffix+a[rson].max_prefix &&a[i].l>a[lson].suf_l))
    {
        a[i].max_all=a[lson].max_suffix+a[rson].max_prefix;
        a[i].l = a[lson].suf_l;
        a[i].r = a[rson].pre_r;
    }
//4.左边的max_suffix+右边的sum
    if(a[i].max_all<a[lson].max_suffix+a[rson].sum || (a[i].max_all==a[lson].max_suffix+a[rson].sum &&a[i].l>a[lson].suf_l))
    {
        a[i].max_all=a[lson].max_suffix+a[rson].sum;
        a[i].l = a[lson].suf_l;
        a[i].r = r;
    }
//5.右边的max_all
    if(a[i].max_all<a[rson].max_all || (a[i].max_all==a[rson].max_all&&a[i].l>a[rson].suf_l))
    {
        a[i].max_all = a[rson].max_all;
        a[i].l = a[rson].l;
        a[i].r = a[rson].r;
    }
//更新前缀与后缀的位置
    if(a[lson].sum+a[rson].max_prefix>a[i].max_prefix)
    {
        a[i].max_prefix=a[lson].sum+a[rson].max_prefix;
        a[i].pre_r = a[rson].pre_r;
    }
    if(a[rson].sum+a[lson].max_suffix>=a[i].max_suffix)
    {
        a[i].max_suffix=a[rson].sum+a[lson].max_suffix;
        a[i].suf_l = a[lson].suf_l;
    }
}

void init(int l,int r,int i)
{
    if(l == r)
    {
        a[i].max_all = a[i].max_prefix = a[i].max_suffix = a[i].sum = s[l];
        a[i].l = a[i].r = a[i].pre_r = a[i].suf_l = l;
        return ;
    }
    int mid = (l+r)/2;
    init(LS);
    init(RS);
    pushup(l,r,i);
}

node query(int i,int l,int r,int L,int R)
{
    if(l==L&&r==R)
    {
        return a[i];
    }
    int mid=(L+R)>>1;
    if(r<=mid)     return  query(lson,l,r,L,mid);
    else if(l>mid) return  query(rson,l,r,mid+1,R);
    else
    {
        node t1=query(lson,l,mid,L,mid);
        node t2=query(rson,mid+1,r,mid+1,R);
        node t;
        t.sum = t1.sum+t2.sum;

        t.max_prefix = t1.max_prefix;
        t.pre_r = t1.pre_r;
        t.max_suffix = t2.max_suffix;
        t.suf_l = t2.suf_l;

        t.max_all = t1.sum+t2.max_prefix;
        t.l = l;
        t.r = t2.pre_r;


        if(t.max_all<t1.max_all || (t.max_all==t1.max_all&&t.l==t1.l))
        {
            t.max_all = t1.max_all;
            t.l = t1.l;
            t.r = t1.r;
        }
        if(t.max_all<t1.max_suffix+t2.max_prefix || (t.max_all==t1.max_suffix+t2.max_prefix &&t.l>t1.suf_l))
        {
            t.max_all=t1.max_suffix+t2.max_prefix;
            t.l = t1.suf_l;
            t.r = t2.pre_r;
        }
        if(t.max_all<t1.max_suffix+t2.sum || (t.max_all==t1.max_suffix+t2.sum &&t.l>t1.suf_l))
        {
            t.max_all=t1.max_suffix+t2.sum;
            t.l = t1.suf_l;
            t.r = t2.r;
        }
        if(t.max_all<t2.max_all || (t.max_all==t2.max_all&&t.l>t2.l))
        {
            t.max_all = t2.max_all;
            t.l = t2.l;
            t.r = t2.r;
        }

        if(t1.sum+t2.max_prefix>t.max_prefix)
        {
            t.max_prefix=t1.sum+t2.max_prefix;
            t.pre_r = t2.pre_r;
        }
        if(t2.sum+t1.max_suffix>=t.max_suffix)
        {
            t.max_suffix=t2.sum+t1.max_suffix;
            t.suf_l = t1.suf_l;
        }
        return t;
    }
}

int main()
{
    int i,j,l,r,cas = 1;
    while(~scanf("%d%d",&n,&m))
    {
        for(i = 1; i<=n; i++)
            scanf("%lld",&s[i]);
        init(1,n,1);
        printf("Case %d:\n",cas++);
        while(m--)
        {
            scanf("%d%d",&l,&r);
            node t=query(1,l,r,1,n);
            printf("%d %d\n",t.l,t.r);
        }
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值