SPOJ GSS1(线段树)

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.

Sample Input
3
-1 2 3
1
1 2
Sample Output
2
题意:给你一个序列,每次给你一个范围,找到这个范围内的最大连续子序列和,直接每次都暴力求特点范围的话,会T
看了题解后才知道要用线段树,太神奇了
借用一下队友发的解释
在这里插入图片描述
本人把从左端开始的:ll
右端开始的:rr
区间最大连续和:you
左子节点 lrt,由子节点 rrt
ac代码

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<math.h>
#include<iomanip>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 5e4 + 5;
int p[N];
struct node
{
	int rr, ll, sum, you;
}tree[N * 4];

void built(int l, int r, int rt)
{
	if (l == r)
	{
		tree[rt].rr = p[l];
		tree[rt].ll = p[l];
		tree[rt].sum = p[l];
		tree[rt].you = p[l];
		return;
	}
	int m = (l + r) >> 1;
	built(l, m, rt << 1);
	built(m + 1, r, rt << 1 | 1);
	int rrt = rt << 1;
	int lrt = rt << 1 | 1;
	tree[rt].ll = max(tree[rrt].ll, tree[rrt].sum + tree[lrt].ll);
	tree[rt].rr = max(tree[lrt].rr, tree[lrt].sum + tree[rrt].rr);
	tree[rt].sum = tree[rrt].sum + tree[lrt].sum;
	tree[rt].you = max(max(tree[rrt].you, tree[lrt].you), tree[rrt].rr + tree[lrt].ll);
}
node query(int L, int R, int l, int r, int rt)
{
	if (L <= l && R >= r)
	{
		return tree[rt];
	}int m = (r + l) >> 1;
	node aa, bb, cc;
	if (L <= m)aa = query(L, R, l, m, rt << 1);
	else aa.ll = aa.rr = aa.you = -INF,aa.sum=0;
	if (R > m)bb = query(L, R, m + 1, r, rt << 1 | 1);
	else bb.ll = bb.rr = bb.you =-INF,bb.sum=0;
	cc.ll = max(aa.ll, aa.sum + bb.ll);
	cc.rr = max(bb.rr, aa.rr + bb.sum);
	cc.sum = aa.sum + bb.sum;
	cc.you = max(max(aa.you, bb.you), aa.rr + bb.ll);
	//cout << cc.ll << " " << cc.rr << " " << cc.sum << " " << cc.you<<endl;
	return cc;
}
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &p[i]);
	}
	int m,x,y;
	built(1, n, 1);
	scanf("%d", &m);
	for (int i = 1; i <= m; i++)
	{
		scanf("%d%d", &x, &y);
		printf("%d\n", query(x, y, 1, n, 1).you);
	}
}在这里插入代码片
发布了109 篇原创文章 · 获赞 35 · 访问量 6025

猜你喜欢

转载自blog.csdn.net/weixin_43965698/article/details/89426452
今日推荐