UVALive - 3938 "Ray, Pass me the dishes!"

注意分清三种情况,并且保证字典序最小

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ls o<<1
#define rs o<<1|1
#define lson L, mid, ls
#define rson mid+1, R, rs

using namespace std;

const int maxn = 5e5 + 10;
typedef long long ll;

int n, m;
ll s[maxn];

struct Node
{
    int vl, vr;//解区间 
    int suf, pre;//后缀的最左端、前缀的最右端 
}tree[maxn<<2];

void pushup(int l, int r, int o)
{
    tree[o].pre = (s[tree[ls].pre]-s[l-1] >= s[tree[rs].pre]-s[l-1]) ? tree[ls].pre : tree[rs].pre;
    tree[o].suf = (s[r]-s[tree[ls].suf-1] >= s[r]-s[tree[rs].suf-1]) ? tree[ls].suf : tree[rs].suf;

    ll v1 = s[tree[ls].vr] - s[tree[ls].vl-1];//起点、终点都在左孩子 
    ll v2 = s[tree[rs].vr] - s[tree[rs].vl-1];//起点、终点都在右孩子 
    ll v0 = s[tree[rs].pre] - s[tree[ls].suf-1];//起点、终点一个在左,一个在右

    tree[o].vl = v1>=v2 ? tree[ls].vl : tree[rs].vl;
    tree[o].vr = v1>=v2 ? tree[ls].vr : tree[rs].vr;

    if(v0 == s[tree[o].vr]-s[tree[o].vl-1])//保证字典序最小 
    {
        if(tree[ls].suf < tree[o].vl)
        {
            tree[o].vl = tree[ls].suf;
            tree[o].vr = tree[rs].pre;
        }
        else if(tree[ls].suf==tree[o].vl && tree[rs].pre<tree[o].vr)
        {
            tree[o].vr = tree[rs].pre;  
        } 
    }
    if(v0 > s[tree[o].vr]-s[tree[o].vl-1])
    {
        tree[o].vl = tree[ls].suf;
        tree[o].vr = tree[rs].pre;      
    }
}

void build(int L, int R, int o)
{
    if(L==R)
    {
        tree[o].pre = tree[o].suf = tree[o].vl = tree[o].vr = L;
        return ;
    }
    int mid = (L+R) >> 1;
    build(lson);
    build(rson);
    pushup(L, R, o);
}

Node query(int l, int r, int L, int R, int o)
{
    if(l<=tree[o].vl && tree[o].vr<=r)
    {
        return tree[o];
    }
    int mid = (L+R) >> 1;
    if(r<=mid)
        return query(l, r, lson);
    if(l>mid)
        return query(l, r, rson);

    Node a = query(l, r, lson);
    Node b = query(l, r, rson);
    Node c;

    c.vl = (s[a.vr]-s[a.vl-1] >= s[b.vr]-s[b.vl-1]) ? a.vl : b.vl;
    c.vr = (s[a.vr]-s[a.vl-1] >= s[b.vr]-s[b.vl-1]) ? a.vr : b.vr;

    c.pre = (s[a.pre]-s[l-1] >= s[b.pre]-s[l-1]) ? a.pre : b.pre;
    c.suf = (s[r]-s[a.suf-1] >= s[r]-s[b.suf-1]) ? a.suf : b.suf;   
    //保证字典序最小
    if(s[b.pre]-s[a.suf-1] == s[c.vr]-s[c.vl-1]) 
    {
        if(a.suf < c.vl)
        {
            c.vl = a.suf;
            c.vr = b.pre;
        }
        if(a.suf==c.vl && b.pre<c.vr)
        {
            c.vr = b.pre;
        }
    }
    if(s[b.pre]-s[a.suf-1] > s[c.vr]-s[c.vl-1])
    {
        c.vl = a.suf;
        c.vr = b.pre;
    }
    return c;
}

int main()
{
    int flag = 1; 
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        memset(s, 0, sizeof s);
        for(int i = 1; i <= n; i++)
        {
            ll x;
            scanf("%lld", &x);
            s[i] = s[i-1] + x;
        }
        printf("Case %d:\n", flag++);
        build(1, n, 1);
        while(m--)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            Node ans = query(a, b, 1, n, 1);
            printf("%d %d\n", ans.vl, ans.vr);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值