[SP1043]GSS1 - Can you answer these queries I

求区间内最大非空子段和,没什么可说的吧。

线段树,每个区间维护从左端开始的最大非空子段和,区间内的最大非空子段和,以右端结束的最大非空子段和,还有区间和。

pushup()的写法要注意,不要漏掉任何一种情况。

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6 inline int read(){
 7     int x=0,f=1;char ch=getchar();
 8     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 9     while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
10     return x*f;
11 }
12 const int MAXN=50005;
13 int n,m,a[MAXN],ql,qr;
14 struct Node{
15     int L,M,R,S;
16 }b[MAXN*4];
17 #define mid ((l+r)>>1)
18 #define lc (o<<1)
19 #define rc ((o<<1)|1)
20 Node mer(Node x,Node y){
21     Node ans;
22     ans.L=max(x.L,x.S+y.L);
23     ans.M=max(x.M,max(y.M,x.R+y.L));
24     ans.R=max(x.R+y.S,y.R);
25     ans.S=x.S+y.S;
26     return ans;
27 }
28 void pushup(int o){
29     b[o]=mer(b[lc],b[rc]);
30 }
31 void build(int o,int l,int r){
32     if(l==r){
33         b[o].L=b[o].M=b[o].R=b[o].S=a[l];
34         return;
35     }
36     build(lc,l,mid);
37     build(rc,mid+1,r);
38     pushup(o);
39 }
40 Node query(int o,int l,int r){
41     if(ql<=l&&r<=qr) return b[o];
42     if(ql>mid) return query(rc,mid+1,r);
43     else if(qr<=mid) return query(lc,l,mid);
44     else return mer(query(lc,l,mid),query(rc,mid+1,r));
45 }
46 int main(){
47     n=read();
48     for(int i=1;i<=n;i++)
49         a[i]=read();
50     build(1,1,n);
51     m=read();
52     while(m--){
53         ql=read(),qr=read();
54         printf("%d\n",query(1,1,n).M);
55     }
56     return 0;
57 }

说起来我一开始把题看成求区间最大值了233......

原文地址:https://www.cnblogs.com/ErkkiErkko/p/9275307.html

时间: 2024-11-12 23:37:57

[SP1043]GSS1 - Can you answer these queries I的相关文章

SP1043 GSS1 - Can you answer these queries I(线段树,区间最大子段和(静态))

题目描述 给出了序列A[1],A[2],…,A[N]. (a[i]≤15007,1≤N≤50000).查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j]:x≤i≤j≤y}. 给定M个查询,程序必须输出这些查询的结果. 输入输出格式 输入格式: 输入文件的第一行包含整数N. 在第二行,N个数字跟随. 第三行包含整数M. M行跟在后面,其中第1行包含两个数字xi和yi. 输出格式: 您的程序应该输出M查询的结果,每一行一个查询. 思路: 我们做这道题首先应该想的,是两个

SP1043 GSS1 - Can you answer these queries I(猫树)

给出了序列A[1],A[2],…,A[N]. (a[i]≤15007,1≤N≤50000).查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j]:x≤i≤j≤y}. 给定M个查询,程序必须输出这些查询的结果. 这就是一个最大子段和,用线段树就能直接搞掉 然后这里学习了一下一个叫做猫树的神奇东西->这里 能做到预处理之后查询$O(1)$ 1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 us

SP1043 GSS1 - Can you answer these queries I 线段树

问题描述 LG-SP1043 题解 GSS 系列第一题. \(q\) 个询问,求 \([x,y]\) 的最大字段和. 线段树,维护 \([x,y]\) 的 \(lmax,rmax,sum,val\) ,向上合并即可. 但是注意询问过程中也需要维护这些信息. \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; template <typename Tp> void read(Tp &x){ x=0;ch

SPOJ GSS1 Can you answer these queries I

Can you answer these queries I Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: GSS164-bit integer IO format: %lld      Java class name: Main You are given a sequence $A[1], A[2], ..., A[N] $. $( |A[i]| \leq

【SP1043】GSS1 - Can you answer these queries I

Description 给出了序列\(A_1,A_2,-,A_n\). \(a_i \leq 15007,1 \leq n \leq 50000\).查询定义如下: 查询\((x,y)=max{a_i+a{i+1}+...+a_j:x \leq i \leq j \leq y }\). 给定M个查询,程序必须输出这些查询的结果. Input 输入文件的第一行包含整数\(n\). 在第二行,\(n\)个数字跟随. 第三行包含整数\(m\). \(m\)行跟在后面,其中第\(1\)行包含两个数字\(

「SP1043」GSS1 - Can you answer these queries I

传送门 Luogu 解题思路 这题就是 GSS3 的一个退化版,不带修改操作的区间最大子段和,没什么好讲的. 细节注意事项 咕咕咕 参考代码 #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cctype> #include <cmath> #include &

GSS1 - Can you answer these queries I(线段树)

前言 线段树菜鸡报告,stO ZCDHJ Orz,GSS基本上都切完了. Solution 考虑一下用线段树维护一段区间左边连续的Max,右边的连续Max,中间的连续Max还有总和,发现这些东西可以相互合并,然后直接写就好了. #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue&

另一个画风的GSS1 - Can you answer these queries I(猫树)

前言 其实我觉得你看猫锟的解释也看不懂(主要是还有一些不良心的讲解者不讲清楚,当然这里不是针对了qwq) 猫锟链接 Solution 考虑我们的线段树是个啥玩意? 每一层都是一堆区间叠在一起. 我们在每一个节点维护的又是什么? 左边的max,右边的max,中间的max,还有sum. 那么我们改变一下: 令\(p_{dps,i}\)表示在深度为\(dps\)的线段树上\(i\)这个节点所在区间的左边的max,右边的max,然后就可以在\(build\)的时候求 再令\(p_{dps,i}\)表示在

SP1716 GSS3 - Can you answer these queries III 线段树

题目传送门:SP1043 GSS1 - Can you answer these queries I 更好的阅读体验 动态维护子段和最大值 前置知识 静态维护子段和最大值:SP1043 GSS1 - Can you answer these queries I 题解传送 题解: 提供结构体指针线段树写法: 设\(l\)为区间左端点, \(r\)为区间右端点: \(ls\)为以\(l\)为左端点的最大子段和, \(rs\)为以\(r\)为右端点的最大子段和; \(sum\)为区间和, \(val\