• 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:
    ",cas++);
            while(m--){
                scanf("%d%d",&l,&r);
                node ans = query(l,r,1,n,1);
                printf("%d %d
    ",ans.lef,ans.rig);
            }
        }
        return 0;
    }
  • 相关阅读:
    ehcache memcache redis 三大缓存男高音
    tomcat启用压缩的方式
    Linux rpm 命令参数使用详解[介绍和应用]
    rpm常用命令及rpm参数介绍
    RPM 命令大全
    BZOJ2298: [HAOI2011]problem a(带权区间覆盖DP)
    BZOJ2037: [Sdoi2008]Sue的小球(区间DP)
    HDU3507 Print Article(斜率优化DP)
    线性代数学习笔记(几何版)
    HDU 2065 "红色病毒"问题(生成函数)
  • 原文地址:https://www.cnblogs.com/kls123/p/10806604.html
Copyright © 2020-2023  润新知