uva 1400 "Ray, Pass me the dishes!" (区间合并 最大子段和+输出左右边界)

题目链接:https://vjudge.net/problem/UVA-1400   

题意:给一串序列,求最大子段,如果有多个,输出字典序最小的那个的左右端点

思路:

之前写过类似的,这个麻烦点需要输出左右端点,我们直接再开几个数组维护左右边界就好了,因为pushup和查询都需要合并操作,我们可以改下pushup传的参数,让查询的时候也可以用pushup合并区间信息。

字典序最小的只要合并和查询的时候都优先向左就好了。

实现代码;

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ll long long
const int M = 5e5+10;
int n;
ll a[M];
struct node{
    ll lsum,rsum,sum,num;
    int lef,rig,lid,rid;
}t[M<<2];

void pushup(node &k,node ls,node rs){
    k.num = ls.num + rs.num;
    if(ls.lsum>=ls.num+rs.lsum)
        k.lsum=ls.lsum,k.lid=ls.lid;
    else
        k.lsum=ls.num+rs.lsum,k.lid=rs.lid;

    if(rs.rsum>rs.num+ls.rsum)
        k.rsum=rs.rsum,k.rid=rs.rid;
    else
        k.rsum=rs.num+ls.rsum,k.rid=ls.rid;

    if(ls.sum>=max(rs.sum,ls.rsum+rs.lsum))
        k.sum=ls.sum,k.lef=ls.lef,k.rig=ls.rig;
    else{
        if(ls.rsum+rs.lsum>=rs.sum)
            k.sum=ls.rsum+rs.lsum,k.lef=ls.rid,k.rig=rs.lid;
        else
            k.sum=rs.sum,k.lef=rs.lef,k.rig=rs.rig;
    }
}

void build(int l,int r,int rt){
    if(l == r){
        t[rt].lid=t[rt].rid=t[rt].lef=t[rt].rig=l;
        t[rt].sum=t[rt].num=t[rt].lsum=t[rt].rsum=a[l];
        return ;
    }
    mid;
    build(lson); build(rson);
    pushup(t[rt],t[rt<<1],t[rt<<1|1]);
}

node query(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return t[rt];
    }
    mid;
    if(R <= m) return query(L,R,lson);
    else if(L > m) return query(L,R,rson);
    else{
        node ret;
        pushup(ret,query(L,R,lson),query(L,R,rson));
        return ret;
    }
}

int main()
{
    int cas = 1,m,l,r;
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(t,0,sizeof(t));
        for(int i = 1;i <= n;i ++) scanf("%lld",&a[i]);
        build(1,n,1);
        printf("Case %d:\n",cas++);
        while(m--){
            scanf("%d%d",&l,&r);
            node ans = query(l,r,1,n,1);
            printf("%d %d\n",ans.lef,ans.rig);
        }
    }
    return 0;
}

 

posted @ 2019-05-03 21:02  冥想选手  阅读(206)  评论(0编辑  收藏  举报