题目链接:https://vjudge.net/problem/SPOJ-GSS1
GSS1 - Can you answer these queries I
You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defined as follows:
Query(x,y) = Max { a[i]+a[i+1]+...+a[j] ; x ≤ i ≤ j ≤ y }.
Given M queries, your program must output the results of these queries.
Input
- The first line of the input file contains the integer N.
- In the second line, N numbers follow.
- The third line contains the integer M.
- M lines follow, where line i contains 2 numbers xi and yi.
Output
Your program should output the results of the M queries, one query per line.
Example
Input: 3 -1 2 3 1 1 2 Output: 2
题意:
给出一个序列。有m个询问:区间[L,R]里的最大连续和是多少?
题解:
1.线段树的结点信息合并。将这n个数按线段树的形式分割下去,然后再从最底层的小区间,往上合并得到大区间:两个对应的小区间有四种合并结果(得到一段连续的区间):1.左连续、右连续、左右不连续、全连续。记录每种合并结果的最大值。
2.对于询问区间,依旧如普通的查询操作一样,拿到线段树里与对应区间,但是需要注意的是:当询问区间被mid分成两段时,需要单独单出来,然后再尝试将两段进行信息合并。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXN = 5e4+10; 18 19 struct node 20 { 21 int a[4]; 22 }; 23 node sum[MAXN<<2]; 24 25 /* 26 0:两边不连续 27 1:左连续 28 2:右连续 29 3:全连续 30 */ 31 void push_up(int fa[], int s1[], int s2[]) 32 { 33 fa[0] = max(max(s1[0], s2[0]),max(max(s1[2],s2[1]), s1[2]+s2[1])); 34 fa[1] = max(max(s1[1],s1[3]), s1[3]+s2[1]); 35 fa[2] = max(max(s2[2],s2[3]), s1[2]+s2[3]); 36 fa[3] = s1[3] + s2[3]; 37 } 38 39 void build(int u, int l, int r) 40 { 41 if(l==r) 42 { 43 scanf("%d", &sum[u].a[3]); //只有一个点,当然是全连续 44 sum[u].a[0] = sum[u].a[1] = sum[u].a[2] = -15007; //其他情况设为不可能 45 return; 46 } 47 48 int mid = (l+r)>>1; 49 build(u*2, l, mid); 50 build(u*2+1, mid+1, r); 51 push_up(sum[u].a, sum[u*2].a, sum[u*2+1].a); 52 } 53 54 node query(int u, int l, int r, int x, int y) 55 { 56 if(x<=l && r<=y) 57 return sum[u]; 58 59 int mid = (l+r)>>1; 60 node ret; 61 if(y<=mid) //询问区间在左边 62 ret = query(u*2, l, mid, x, y); 63 else if(x>=mid+1) //询问区间在右边 64 ret = query(u*2+1, mid+1, r, x, y); 65 else //询问区间被分割成两段,因而还要调用push_up尝试将两子区间合并 66 { 67 node t1 = query(u*2, l, mid, x, mid); 68 node t2 = query(u*2+1, mid+1, r, mid+1, y); 69 push_up(ret.a, t1.a, t2.a); 70 } 71 return ret; 72 } 73 74 int main() 75 { 76 int n, m; 77 scanf("%d", &n); 78 build(1,1,n); 79 scanf("%d", &m); 80 while(m--) 81 { 82 int l, r; 83 scanf("%d%d", &l,&r); 84 node ret = query(1,1,n,l,r); 85 int t1 = max(ret.a[0], ret.a[1]); //取四种连续情况的最大值 86 int t2 = max(ret.a[2], ret.a[3]); 87 printf("%d ", max(t1,t2)); 88 } 89 }