LA3938Ray, Pass me the Dishes, LA 3938 , 線段樹,區間查詢

題目鏈接:


https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1939


來自:劉汝佳大白書P201.


解題思路:


機關一棵線段樹,此中每個結點保護三個值,記錄最大前綴和,最大後綴和最大連氣兒和。


最大連氣兒和要麼完全在左段,要麼完全在右段,要麼在跨越中線。就是會是左段的最大後綴和+右段的最大前綴和。。。。

#include <iostream>
#include <cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<math.h>
#include<queue>
#include<utility>

#define INF 2000000000
#define maxn 500005LL
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define ls(o) o<<1
#define rs(o) o<<1|1
using namespace std;

typedef pair<int,int> Interval;
typedef long long ll;

ll prefix_sum[510005];

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

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

Interval better(Interval a,Interval b)
{
    ll t1=sum(a),t2=sum(b);
    if(t1==t2)return a<b?a:b;
    else{
        return t1>t2?a:b;
    }
}

struct line_tree{
    int prefix;
    int suffix;
    int l, r;
    Interval sub;
}tree[maxn<<2];

void build(int l,int r,int o)
{
    tree[o].l=l,tree[o].r=r;
    if(l==r){
        tree[o].prefix=tree[o].suffix=l;
        tree[o].sub = make_pair(l,l);
        return ;
    }
    int mid = (l+r)>>1;
    build(l,mid,ls(o));
    build(mid+1,r,rs(o));

    ll t1 = sum(l,tree[ls(o)].prefix);
    ll t2 = sum(l,tree[rs(o)].prefix);
    if(t1==t2)tree[o].prefix = min(tree[ls(o)].prefix,tree[rs(o)].prefix);
    else tree[o].prefix = t1>t2?tree[ls(o)].prefix:tree[rs(o)].prefix;

    t1 = sum(tree[ls(o)].suffix,r);
    t2 = sum(tree[rs(o)].suffix,r);
    if(t1==t2)tree[o].suffix = min(tree[ls(o)].suffix,tree[rs(o)].suffix);
    else tree[o].suffix = t1>t2?tree[ls(o)].suffix:tree[rs(o)].suffix;

    tree[o].sub = better(tree[ls(o)].sub,tree[rs(o)].sub);
    tree[o].sub = better(tree[o].sub,make_pair(tree[ls(o)].suffix,tree[rs(o)].prefix));
}

Interval query_prefix(int l,int r,int o)
{
    if(tree[o].prefix<=r)return make_pair(l,tree[o].prefix);
    if(r<=tree[ls(o)].r)return query_prefix(l,r,ls(o));
    Interval t = query_prefix(l,r,rs(o));
    t.first = l;
    return better(t,make_pair(l,tree[ls(o)].prefix));
}

Interval query_suffix(int l,int r,int o)
{
    if(tree[o].suffix>=l)return make_pair(tree[o].suffix,r);
    if(l>=tree[rs(o)].l)return query_suffix(l,r,rs(o));
    Interval t = query_suffix(l,r,ls(o));
    t.second = r;
    return better(t,make_pair(tree[rs(o)].suffix,r));
}
Interval query(int l,int r,int o)
{
    if(l<=tree[o].l&&tree[o].r<=r)return tree[o].sub;
    if(r<=tree[ls(o)].r)return query(l,r,ls(o));
    if(l>=tree[rs(o)].l)return query(l,r,rs(o));
    Interval t1 = query_suffix(l,r,ls(o));
    Interval t2 = query_prefix(l,r,rs(o));
    Interval t3 = better(query(l,r,ls(o)),query(l,r,rs(o)));
    return better(t3,make_pair(t1.first,t2.second));
}

int main()
{
    int n,m,t=1;
    while(scanf("%d%d",&n,&m)==2){
        printf("Case %d:\n",t++);
        prefix_sum[0] = 0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&prefix_sum[i]);
            prefix_sum[i]+=prefix_sum[i-1];
        }
        build(1,n,1);
        int a,b;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            Interval p = query(a,b,1);
            printf("%d %d\n",p.first,p.second);
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章