zoukankan      html  css  js  c++  java
  • SPOJ GSS5 Can you answer these queries V 线段树

    $ Rightarrow $ 戳我进SPOJ原题

    GSS5 - Can you answer these queries V

     

    Time limit: 0.132s $ quad $ Source limit: 50000B $ quad $ Memory limit:1536MB

      You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| <= 10000 , 1 <= N <= 10000 ). A query is defined as follows: Query(x1,y1,x2,y2) = Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 <= j <= y2 and x1 <= x2 , y1 <= y2 }. Given M queries (1 <= M <= 10000), your program must output the results of these queries.  

    Input

    The first line of the input consist of the number of tests cases <= 5. Each case consist of the integer N and the sequence A.
    Then the integer M. M lines follow, contains 4 numbers x1, y1, x2 y2.
     

    Output

    Your program should output the results of the M queries for each test case, one query per line.
     

    Examples

     Input:
     2
     6 3 -2 1 -4 5 2
     2
     1 1 2 3
     1 3 2 5
     1 1
     1
     1 1 1 1
    
     Output:
     2
     3
     1
    

     

    题意翻译

    给定一个序列。查询左端点在 $ [x_1, y_1] $ 之间,且右端点在 $ [x_2, y_2] $ 之间的最大子段和,
    数据保证 $ x_1leq x_2,y_1leq y_2 $ ,但是不保证端点所在的区间不重合

    感谢@Anoxiacxy 提供的翻译
     

    思路

    • 如果 $ x_1 le y_1 <x_2 le y_2 $

      • 区间分离,中间必须取,两端区间靠近中间选最大
         
    • 如果 $ x_1 le x_2 le y_1 le y_2 $

      • 选取 $ [x_2,y_1] $ 中的最大子段和
        选取 $ [x_1,x_2-1] $ 的最右端部分,和 $ [x_2,y_1] $ 的最左端部分
        选取 $ [x_2,y_1] $ 的最右端部分,和 $ [y_1+1,y_2] $ 的最左端部分
        选取 $ [x_1,x_2-1] $ 的最右端部分,$ [x_2,y_1] $ 的全部,和 $ [y_1+1,y_2] $ 的最左端部分
         

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 100010
    #define int long long
    struct tree{ int l,r,lmax,rmax,max,sum; }t[maxn<<2];
    int T,n,m,x1,x2,y1,y2,s[maxn],ans;
    void pushup(int o){
        t[o].sum=t[o<<1].sum+t[o<<1|1].sum;
        t[o].lmax=max(t[o<<1].sum+t[o<<1|1].lmax,t[o<<1].lmax);
        t[o].rmax=max(t[o<<1|1].sum+t[o<<1].rmax,t[o<<1|1].rmax);
        t[o].max=max(t[o<<1].rmax+t[o<<1|1].lmax,max(t[o<<1].max,t[o<<1|1].max));
    }
    void build(int o,int l,int r){
        t[o].l=l; t[o].r=r;
        if(l==r){ 
            scanf("%lld",&t[o].sum); 
            s[l]=s[l-1]+t[o].sum;
            t[o].max=t[o].lmax=t[o].rmax=t[o].sum;
            return;
        }
        int mid=l+r>>1;
        build(o<<1,l,mid); build(o<<1|1,mid+1,r);
        pushup(o);
    }
    int ql(int o,int l,int r){
        if(l>r) return 0;
        if(t[o].l==l&&t[o].r==r) return t[o].lmax;
        int mid=t[o].l+t[o].r>>1;
        if(l>mid) return ql(o<<1|1,l,r);
        else if(r<=mid) return ql(o<<1,l,r);
        else return max(ql(o<<1,l,mid),s[mid]-s[l-1]+ql(o<<1|1,mid+1,r));
    }
    int qr(int o,int l,int r){
        if(l>r) return 0;
        if(t[o].l==l&&t[o].r==r) return t[o].rmax;
        int mid=t[o].l+t[o].r>>1;
        if(l>mid) return qr(o<<1|1,l,r);
        else if(r<=mid) return qr(o<<1,l,r);
        else return max(qr(o<<1|1,mid+1,r),s[r]-s[mid]+qr(o<<1,l,mid));
    }
    int qm(int o,int l,int r){
        if(l>r) return 0;
        if(t[o].l==l&&t[o].r==r) return t[o].max;
        int mid=t[o].l+t[o].r>>1;
        if(l>mid) return qm(o<<1|1,l,r);
        else if(r<=mid) return qm(o<<1,l,r);
        else {
            int Lmax=ql(o<<1|1,mid+1,r);
            int Rmax=qr(o<<1,l,mid);
            return max(Lmax+Rmax,max(qm(o<<1,l,mid),qm(o<<1|1,mid+1,r)));
        }
    }
    signed main(){
        scanf("%lld",&T);
        while(T--){
            scanf("%lld",&n);
            build(1,1,n);
            scanf("%lld",&m);
            while(m--){
                scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
                if(x2>y1){
                    ans=s[x2-1]-s[y1];
                    ans+=qr(1,x1,y1)+ql(1,x2,y2);
                    printf("%lld
    ",ans);
                } else {
                    ans=qm(1,x2,y1);
                    ans=max(ans,qr(1,x2,y1)+ql(1,y1+1,y2));
                    ans=max(ans,ql(1,x2,y1)+qr(1,x1,x2-1));
                    ans=max(ans,qr(1,x1,x2-1)+s[y1]-s[x2-1]+ql(1,y1+1,y2));
                    printf("%lld
    ",ans);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Expert Shell Scripting
    tr [a-z] [A-Z]
    ssh
    scp
    sort 命令
    cut 命令使用
    oracle 对象权限 系统权限 角色权限
    从linux内核中学到的编程技巧 【转】
    2019.3.16 最小生成树之城市改造
    2019.1.23 01迷宫
  • 原文地址:https://www.cnblogs.com/PotremZ/p/SPOJGSS5.html
Copyright © 2011-2022 走看看