码迷,mamicode.com
首页 > 其他好文 > 详细

UVALive 3938 Ray, Pass me the dishes! (动态最大连续和)

时间:2015-09-08 20:08:24      阅读:296      评论:0      收藏:0      [点我收藏+]

标签:

题意:求一个动态区间的最大连续和。

静态版本的O(n)算法显示不适用了,但是可以用线段树分治,因为一个连续和要在两边的区间,要么跨越两边,对于一个结点维护最大前缀和,后缀和,子区间连续和。

题目要求输出区间,所以还要保存连续和最大的区间,以及前缀和,后缀和的位置。为了维护最大前缀和以及后缀和还需要一个区间和。

写的时候稍微麻烦一点,更新写成一个函数会方便很多。还好一遍过了。。。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 5e5+2;
typedef long long ll;
struct Seg
{
    ll pre,suf,sub,sum;
    int l,r,pr,sl;
}tr[maxn<<2];
#define lid (id<<1)
#define rid (id<<1|1)
int n,m,a[maxn];
int ql,qr;

void updata(Seg&u,Seg&v1,Seg&v2)
{
    if(v1.pre >= v1.sum+v2.pre){//y
        u.pr = v1.pr; u.pre = v1.pre;
    }else {
        u.pr = v2.pr; u.pre = v1.sum+v2.pre;
    }

    if(v2.suf <= v2.sum+v1.suf){//x
        u.sl = v1.sl; u.suf = v2.sum+v1.suf;
    }else {
        u.sl = v2.sl; u.suf = v2.suf;
    }

    if(v1.sub >= v2.sub){
        u.l = v1.l; u.r = v1.r; u.sub = v1.sub;
    }else {
        u.l = v2.l; u.r = v2.r; u.sub = v2.sub;
    }
    if(u.sub < v1.suf+v2.pre || (u.sub == v1.suf+v2.pre && (u.l>v1.sl ||(u.l == v1.sl && u.r > v2.pr) ) ) ){
        u.sub = v1.suf+v2.pre; u.l = v1.sl; u.r = v2.pr;
    }

    u.sum = v1.sum + v2.sum;
}

void build(int l = 1,int r = n,int id = 1)
{
    Seg &u = tr[id];
    if(l == r) {
        u.pre = u.suf = u.sub = u.sum = a[l];
        u.l = u.r = u.pr = u.sl = l;
        return;
    }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    build(l,mid,lc);
    build(mid+1,r,rc);
    Seg &v1 = tr[lc],v2 = tr[rc];
    updata(tr[id],tr[lc],tr[rc]);


}

Seg query(int l = 1,int r = n, int id = 1)
{
    if(ql<=l&&r<=qr) { return tr[id]; }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    Seg ret;
    if(ql<=mid && mid<qr){
        Seg L = query(l,mid,lc), R = query(mid+1,r,rc);
        updata(ret,L,R);
        return ret;
    }
    if(qr <= mid) {
        return query(l,mid,lc);
    }
    return query(mid+1,r,rc);
}

int main()
{
    //freopen("in.txt","r",stdin);
    int kas = 0;
    while(~scanf("%d%d",&n,&m)){
        for(int i = 1; i <= n; i++) scanf("%d",a+i);
        build();
        printf("Case %d:\n",++kas);
        while(m--){
            int x,y; scanf("%d%d",&x,&y);
            ql = x,qr = y;
            Seg ans = query();
            printf("%d %d\n",ans.l,ans.r);
        }
    }
    return 0;
}

 

UVALive 3938 Ray, Pass me the dishes! (动态最大连续和)

标签:

原文地址:http://www.cnblogs.com/jerryRey/p/4792519.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!