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

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int N=101000;
     8 int a[N],n,m,t;
     9 struct tree{
    10     int l,r,sum,lx,rx,maxx;
    11 }tr[N*8];
    12 void update(int now){
    13     int ls=now*2;int rs=now*2+1;
    14     tr[now].maxx=max(tr[ls].maxx,max(tr[rs].maxx,tr[ls].rx+tr[rs].lx));
    15     tr[now].lx=max(tr[ls].lx,tr[ls].sum+tr[rs].lx);
    16     tr[now].rx=max(tr[rs].rx,tr[rs].sum+tr[ls].rx);
    17     tr[now].sum=tr[ls].sum+tr[rs].sum;
    18 }
    19 void build(int l,int r,int now){
    20     tr[now].l=l;tr[now].r=r;
    21     if(l==r){
    22         tr[now].sum=a[l];
    23         tr[now].lx=tr[now].rx=tr[now].maxx=a[l];
    24         return;
    25     }
    26     int mid=(tr[now].l+tr[now].r)>>1;
    27     build(l,mid,now*2);
    28     build(mid+1,r,now*2+1);
    29     update(now);
    30 }
    31 int check(int l,int r,int k,int now){
    32     if(l>r)return 0; 
    33     if(tr[now].l==l&&tr[now].r==r){
    34         if(k==1)return tr[now].maxx;
    35         else if(k==4)return tr[now].sum;
    36         else if(k==2)return tr[now].rx;
    37         else return tr[now].lx;
    38     }
    39     int mid=(tr[now].l+tr[now].r)>>1;
    40     if(l>mid)return check(l,r,k,now*2+1);
    41     else if(r<=mid) return check(l,r,k,now*2);
    42     else{
    43         if(k==1)return max(check(l,mid,1,now*2),max(check(mid+1,r,1,now*2+1),check(l,mid,2,now*2)+check(mid+1,r,3,now*2+1)));
    44         else if(k==2)return max(check(mid+1,r,2,now*2+1),check(mid+1,r,4,now*2+1)+check(l,mid,2,now*2));
    45         else if(k==3)return max(check(l,mid,3,now*2),check(l,mid,4,now*2)+check(mid+1,r,3,now*2+1));
    46         else return check(l,mid,4,now*2)+check(mid+1,r,4,now*2+1);
    47     }
    48 }
    49 int main(){
    50     scanf("%d",&t);
    51     for(int z=1;z<=t;z++){
    52         scanf("%d",&n);
    53         for(int i=1;i<=n;i++){
    54             scanf("%d",&a[i]);
    55         } 
    56         build(1,n,1);
    57         scanf("%d",&m);
    58         for(int i=1,x,y,xx,yy;i<=m;i++){
    59             scanf("%d%d%d%d",&x,&y,&xx,&yy);
    60             if(xx>y){
    61                 printf("%d
    ",check(x,y,2,1)+check(y+1,xx-1,4,1)+check(xx,yy,3,1));
    62             }else if(y==yy){
    63                 printf("%d
    ",max(check(xx,yy,1,1),check(xx,yy,3,1)+check(x,xx-1,2,1)));
    64             }else{
    65                 printf("%d
    ",max(check(x,xx-1,2,1)+check(xx,y,3,1),max(check(x,xx-1,2,1)+check(xx,y,4,1)+check(y+1,yy,3,1),max(check(xx,y,2,1)+check(y+1,yy,3,1),check(xx,y,1,1)))));
    66             }
    67         }
    68     } 
    69     return 0;
    70 }
    View Code

    题目大意

    给定一个序列。查询左端点在 [x1,y1][x_1, y_1][x1,y1] 之间,且右端点在 [x2,y2][x_2, y_2][x2,y2] 之间的最大子段和,数据保证 x1≤x2,y1≤y2x_1leq x_2,y_1leq y_2x1x2,y1y2 ​ ,但是不保证端点所在的区间不重合

    题解

    看起来很难其实就是分类讨论一下:

    如果x1<=y1<x2<=y2

    区间分离,中间必须取,两端区间靠近中间选最大

    如果x1<=x2<=y1<=y2

    选取[x2,y1]中的最大子段和

    选取[x1,x2-1]的最右端部分,和[x2,y1]的最左端部分

    选取[x2,y1]的最右端部分,和[y1+1,y2]的最左端部分

    选取[x1,x2-1]的最右端部分,[x2,y1]的全部,和[y1+1,y2]的最左端部分

    代码还是要注意一些细节,比如,l>r,在递归里特判一下,还有就是区间的边界需要注意不要算重了。

  • 相关阅读:
    json&pickle模块
    Linux BASH 常用命令
    Vmware安装Kali2020
    CentOS7部署Prometheus
    CentOS7部署FreeRadius3.0及WEB管理界面DaloRadius
    Cisco VRRP、TRACK、SLA配置
    Cisco L2TP OVER IPSEC
    Cisco PPTP Server Configration
    华为S5700交换机初始化和配置TELNET远程登录
    华为S5720常用命令
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9303074.html
Copyright © 2011-2022 走看看