关闭

UVa 1400 "Ray, Pass me the dishes!"(线段树)

222人阅读 评论(0) 收藏 举报
分类:

题目链接:http://acm.hust.edu.cn/vjudge/problem/36216


大意:给出n个数m个询问,对于每个询问(a,b),求(a,b)区间内的最大连续和区间(x,y),若有多组解,应使二元组(x,y)尽可能小。


思路:

(以下区间均为闭区间)设m为区间(a,b)的中点,则(a,b)内的最大连续和区间有三种情况,一是区间落在(a,m)内,二是落在(m+1,b)内,三是区间(a,m)的最大后缀和区间加上区间(m+1,b)的最大前缀区间。所以在建树时,要维护三个值,设该结点所对应区间为(a,b),则一为最大和区间(x,y),二为其最大前缀区间(a,x),三为最大后缀区间(x,b)。


而一个区间的最大前缀区间为(a,左子树最大前缀区间的右端点)或(a,右子树最大前缀和区间的右端点),最大后缀区间与其相似。最大和区间要么完全分布在左子树或右子树,要么是左右子树均有(此时则为左子树的最大后缀区间加上右子树的 最大前缀区间)


在查询时同样也是三种情况,但是若待查询区间落在结点区间的左右两区间内,此时不能简单认为答案就是左子树的最大后缀加上右子树的最大前缀,因为这俩区间并起来可能超出了待查询区间的范围,所以此时要特殊讨论一下。这里简单举个例子,假设结点所对应区间为(A,B),其中点为M,待查询区间为(a,b),且a<=M<b,我们要从(A,M)中找一个最大后缀(L,M),其中L>=a。首先,(A,M)的最大后缀区间在建树时已经算出来了,假设为(aa,M),那么如果aa>=x,则答案就是(aa,M)。如果不满足,设(A,M)的中点为m,那么最大后缀区间的左端点可能落在(A,m)内,也可能是(m+1,M)内,分情况讨论即可。详见代码。


#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lc rt<<1
#define rc rt<<1|1
using namespace std;

typedef long long ll;
typedef pair<int,int> Interval;
const int maxn = 5e5 + 5;
const int maxnode = maxn<<1;
ll pre_sum[maxn];

ll sum(int l, int r)
{
    return pre_sum[r] - pre_sum[l-1];
}

ll sum(Interval p)
{
    return sum(p.first, p.second);
}

Interval better(Interval a, Interval b) //在和相同的情况下选择更优区间
{
    if (sum(a) != sum(b)) return sum(a) > sum(b) ? a : b;
    return a < b ? a : b;
}

struct IntervalTree
{
    int max_prefix[maxnode]; //最大前缀
    int max_suffix[maxnode]; //最大后缀
    Interval max_sub[maxnode]; //最大和

    void clear()
    {
        memset(max_prefix, 0, sizeof max_prefix);
        memset(max_suffix, 0, sizeof max_suffix);
        memset(max_sub, 0, sizeof max_sub);
    }

    void build(int l, int r, int rt)
    {
        if (l == r) {
            max_sub[rt] = Interval(l,r);
            max_prefix[rt] = l;
            max_suffix[rt] = r;
            return;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        //最大前缀区间
        max_prefix[rt] = better(Interval(l,max_prefix[lc]), Interval(l,max_prefix[rc])).second;
        //最大后缀区间
        max_suffix[rt] = better(Interval(max_suffix[lc],r), Interval(max_suffix[rc],r)).first;
        //最大和区间
        max_sub[rt] = better(max_sub[lc], max_sub[rc]);
        max_sub[rt] = better(max_sub[rt], Interval(max_suffix[lc], max_prefix[rc]));
    }

    Interval query_suffix(int qL, int qR, int l, int r, int rt)
    {
        if (max_suffix[rt] >= qL) return Interval(max_suffix[rt],qR);
        int m = (l + r) >> 1;
        if (qL > m) return query_suffix(qL,qR,rson);
        Interval A = query_suffix(qL,m,lson);
        A.second = qR;
        return better(A, Interval(max_suffix[rc],qR));
    }

    Interval query_prefix(int qL, int qR, int l, int r, int rt)
    {
        if (max_prefix[rt] <= qR) return Interval(qL,max_prefix[rt]);
        int m = (l + r) >> 1;
        if (qR <= m) return query_prefix(qL,qR,lson);
        Interval A = query_prefix(m+1,qR,rson);
        A.first = qL;
        return better(A, Interval(qL,max_prefix[lc]));
    }

    Interval query(int qL, int qR, int l, int r, int rt)
    {
        if (qL <= l && r <= qR) return max_sub[rt];
        int m = (l + r) >> 1;
        if (qR <= m) return query(qL,qR,lson);
        if (qL > m) return query(qL,qR,rson);
        Interval A = better(query(qL,m,lson), query(m+1,qR,rson));
        Interval B = query_suffix(qL,m,lson);
        Interval C = query_prefix(m+1,qR,rson);
        return better(A, Interval(B.first, C.second));
    }
};

IntervalTree Sum;

int main()
{
    int n,m,kase = 0;
    while(~scanf("%d%d",&n,&m)) {
        for (int i = 1; i <= n; i++) {
            int a;
            scanf("%d",&a);
            pre_sum[i] = pre_sum[i-1] + a;
        }
        printf("Case %d:\n", ++kase);
        Sum.clear();
        Sum.build(1,n,1);
        while(m--) {
            int a,b;
            scanf("%d%d",&a,&b);
            Interval ans = Sum.query(a,b,1,n,1);
            printf("%d %d\n",ans.first,ans.second);
        }
    }
    return 0;
}


0
0
查看评论

UVA 1400 "Ray, Pass me the dishes!" (线段树)

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68200#problem/J 题意:给一个长度为n的整数数列,然后给m个询问,对于每个询问(a, b)给出该区间内最大子序列之和的两个下标 思路:询问次数很多,...
  • u013742332
  • u013742332
  • 2015-01-25 22:14
  • 312

uva 1400 "Ray, Pass me the dishes!" 线段树

代码:
  • a601025382s
  • a601025382s
  • 2014-08-02 18:47
  • 1073

UVA - 1400"Ray, Pass me the dishes!"(线段树)

UVA - 1400"Ray, Pass me the dishes!"(线段树) 题目链接 题目大意:给你N个数字,要求你动态的给出L到R之间,X>= L && Y 解题思路:结点保存三个附加线段,max_sub, max_suffix,...
  • u012997373
  • u012997373
  • 2014-09-27 09:41
  • 785

uva 1400 - "Ray, Pass me the dishes!"(线段树)

题目链接:uva 1400 - "Ray, Pass me the dishes!" 题目大意:给定一个长度为n个整数序列,对m次询问作出回答,对于每次询问(a,b),找到两个下标x,y使得x到y的连续和为区间a,b中最大的连续和,如果存在多解优先x小,然后y小。 解...
  • u011328934
  • u011328934
  • 2014-08-24 23:44
  • 941

UVA 1400 "Ray, Pass me the dishes!"(线段树)

训练指南上的线段树写法跟平时写的不一样,写得好难受。#include #include #include #include using namespace std; #define rep(i,a,b) for(int i=(a);i<(b);i++) #define ss(x) scanf(...
  • qq_33901573
  • qq_33901573
  • 2016-10-21 20:15
  • 70

LA3938:"Ray, Pass me the dishes!"(线段树)

Description After doing Ray a great favor to collect sticks for Ray, Poor Neal becomes very hungry. In return for Neal's help, Ray makes a grea...
  • libin56842
  • libin56842
  • 2015-06-13 23:52
  • 1727

1400 - "Ray, Pass me the dishes!"

第一次做线段树题目,确实一点也不会,想了很久,首先是线段树怎么作用,每一步会产生什么影响。 首先,线段树的每次更新都更新了什么,为什么要这么更新,尤其是更新的区间,虽说原理很简单,就是要么在左子树, 要么在右子树,要么兼顾左右子树,所以如果是在左子树,那就查找左子树,否则右子树,或者左右子树都查找,...
  • moyan_min
  • moyan_min
  • 2013-10-07 20:37
  • 1226

UVA 1400 1400 - "Ray, Pass me the dishes!"(线段树)

UVA 1400 - "Ray, Pass me the dishes!" 题目链接 题意:给定一个序列,每次询问一个[L,R]区间,求出这个区间的最大连续子序列和 思路:线段树,每个节点维护3个值,最大连续子序列,最大连续前缀序列,最大连续后缀序列,那么每次p...
  • u011217342
  • u011217342
  • 2014-07-29 00:02
  • 1262

UVA 1400 Ray, Pass me the dishes!

【题意】              给定一个长度为n的序列fi,然后做m次询问,每次询问[l,r]输出这段区间内和最大的子区间。如果存在多个和最大,那取x较小的,如果还是相同,取...
  • just_sort
  • just_sort
  • 2016-07-28 09:01
  • 117

uva 1400 "Ray, Pass me the dishes!"

uva 1400 "Ray, Pass me the dishes!"
  • NNDXNM
  • NNDXNM
  • 2015-04-02 23:23
  • 299
    个人资料
    • 访问:21196次
    • 积分:1325
    • 等级:
    • 排名:千里之外
    • 原创:116篇
    • 转载:5篇
    • 译文:0篇
    • 评论:0条
    文章分类