• SP2916 GSS5


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

    这题可以分为几种情况讨论

    $y_1<x_2$

    那么这个时候发现$[y_1+1,x_2-1]$里的数必须得选,并选出$[x1,y1]$的最大后缀和$[x2,y2]$的最大前缀。用结构体维护一下就好了

    $y_1geq x_2$

    发现这个时候左右端点所在区间的情况分别如下

    $l$在$[x_1,x_2]$,$r$在$[x_2,y_1]$,那么只要查询$[x_1,x_2]$的最大后缀和$[x_2,y_1]$的最大前缀

    $l$在$[x_1,x_2]$,$r$在$[y_1,y_2]$,那么只要查询$[x_1,x_2]$的最大后缀和$[x_2,y_2]$的最大前缀

    $l$在$[x_2,y_1]$,$r$在$[x_2,y_1]$,那么只要查询$[x_2,y_1]$的最大子段和

    $l$在$[x_2,y_1]$,$r$在$[y_1,y_2]$,那么只要查询$[x_2,y_1]$的最大后缀和$[y_1,y_2]$的最大前缀

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define ls (p<<1)
     6 #define rs (p<<1|1)
     7 using namespace std;
     8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     9 char buf[1<<21],*p1=buf,*p2=buf;
    10 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    11 int read(){
    12     #define num ch-'0'
    13     char ch;bool flag=0;int res;
    14     while(!isdigit(ch=getc()))
    15     (ch=='-')&&(flag=true);
    16     for(res=num;isdigit(ch=getc());res=res*10+num);
    17     (flag)&&(res=-res);
    18     #undef num
    19     return res;
    20 }
    21 char sr[1<<21],z[20];int C=-1,Z;
    22 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    23 void print(int x){
    24     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    25     while(z[++Z]=x%10+48,x/=10);
    26     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    27 }
    28 const int N=1e4+5;int a[N],n,m;
    29 struct node{int pre,mid,suf,sum;}b[N<<2];
    30 node merge(node l,node r){
    31     node ans;
    32     ans.pre=max(l.pre,l.sum+r.pre);
    33     ans.mid=max(max(l.mid,r.mid),l.suf+r.pre);
    34     ans.suf=max(l.suf+r.sum,r.suf);
    35     ans.sum=l.sum+r.sum;
    36     return ans;
    37 }
    38 void upd(int p){b[p]=merge(b[ls],b[rs]);}
    39 void build(int p,int l,int r){
    40     if(l==r) return (void)(b[p].pre=b[p].mid=b[p].suf=b[p].sum=a[l]);
    41     int mid=(l+r)>>1;
    42     build(ls,l,mid),build(rs,mid+1,r);
    43     upd(p);
    44 }
    45 node query(int p,int l,int r,int ql,int qr){
    46     if(ql>qr) return (node){0,0,0,0};
    47     if(ql<=l&&qr>=r) return b[p];
    48     int mid=(l+r)>>1;
    49     if(qr<=mid) return query(ls,l,mid,ql,qr);
    50     else if(ql>mid) return query(rs,mid+1,r,ql,qr);
    51     else return merge(query(ls,l,mid,ql,qr),query(rs,mid+1,r,ql,qr));
    52 }
    53 int get(int l1,int r1,int l2,int r2){
    54     if(r1<l2){
    55         int tmp=query(1,1,n,l1,r1).suf;
    56         tmp+=query(1,1,n,r1+1,l2-1).sum;
    57         tmp+=query(1,1,n,l2,r2).pre;
    58         return tmp;
    59     }
    60     int ans=query(1,1,n,l2,r1).mid;
    61     if(l1<l2) cmax(ans,query(1,1,n,l1,l2).suf+query(1,1,n,l2,r2).pre-a[l2]);
    62     if(r2>r1) cmax(ans,query(1,1,n,l1,r1).suf+query(1,1,n,r1,r2).pre-a[r1]);
    63     return ans;
    64 }
    65 int main(){
    66 //    freopen("testdata.in","r",stdin);
    67     int T=read();
    68     while(T--){
    69         n=read();
    70         for(int i=1;i<=n;++i) a[i]=read();
    71         build(1,1,n);
    72         m=read();
    73         while(m--){
    74             int l1=read(),r1=read(),l2=read(),r2=read();
    75             print(get(l1,r1,l2,r2));
    76         }
    77     }
    78     return Ot(),0;
    79 }
  • 相关阅读:
    javaScript设计模式探究【1】
    Java基础算法集50题
    DataTable学习笔记排序细则、列隐藏[3]
    javaScript设计模式探究【4】工厂模式
    javaScript设计模式探究【3】
    一次面试感想+js最近学习体会
    DataTable学习笔记范例应用篇[2]
    腾讯2013实习生招聘面经
    初品cakephp
    php编译中配置libxml2的错误
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9826507.html
Copyright © 2020-2023  润新知