标签:取出 树节点 iostream str 题意 线段 函数 cin void
大致题意:求区间最大子段和,不带修改。
题解:
对于每个线段树节点。维护以下几个值:
l, r:左右端点
sum:区间和
val:区间最大子段和
lv:一定包括区间左端点的最大子段和
rv:一定包括区间右端点的最大子段和
注意,查询的时候。我们不能写成以下版本。
if(l <= mid) res = max(res, ask(p << 1, l, r));
if(r > mid) res = max(res, ask(p << 1 | 1, l, r));
return res;
T ask(int p, int l, int r) //注意这里的函数返回值是一个结构体,方便操作
{
if(t[p].l >= l && t[p].r <= r) return t[p];
int mid = t[p].l + t[p].r >> 1;
if(mid < l) return ask(p2, l, r); //答案都来自右儿子
else if(mid >= r) return ask(p1, l, r); //答案都来自左儿子
else //答案来自左儿子或右儿子或(左右儿子信息融合后的信息)
{
T t1 = ask(p1, l, r), t2 = ask(p2, l, r), now;
now.sum = t1.sum + t2.sum;
now.lv = max(t1.lv, t1.sum + t2.lv);
now.rv = max(t2.rv, t2.sum + t1.rv);
now.l = l, now.r = r;
now.val = max(max(t1.val, t2.val), t1.rv + t2.lv);
return now;
}
}
#include <iostream>
#include <cstdio>
#define N 50005
#define p1 (p << 1)
#define p2 (p << 1 | 1)
using namespace std;
struct T {int l, r, val, lv, rv, sum;} t[N * 4];
int n, m;
int read()
{
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x *= f;
}
void up(int p)
{
t[p].sum = t[p1].sum + t[p2].sum;
t[p].lv = max(t[p1].lv, t[p1].sum + t[p2].lv);
t[p].rv = max(t[p2].rv, t[p2].sum + t[p1].rv);
t[p].val = max(t[p1].rv + t[p2].lv, max(t[p1].val, t[p2].val));
}
void build(int p, int l, int r)
{
t[p].l = l, t[p].r = r;
if(l == r)
{
int v = read();
t[p].lv = t[p].rv = v;
t[p].val = t[p].sum = v;
return;
}
int mid = l + r >> 1;
build(p1, l, mid), build(p2, mid + 1, r);
up(p);
}
T ask(int p, int l, int r)
{
if(t[p].l >= l && t[p].r <= r) return t[p];
int mid = t[p].l + t[p].r >> 1;
if(mid < l) return ask(p2, l, r);
else if(mid >= r) return ask(p1, l, r);
else
{
T t1 = ask(p1, l, r), t2 = ask(p2, l, r), now;
now.sum = t1.sum + t2.sum;
now.lv = max(t1.lv, t1.sum + t2.lv);
now.rv = max(t2.rv, t2.sum + t1.rv);
now.l = l, now.r = r;
now.val = max(max(t1.val, t2.val), t1.rv + t2.lv);
return now;
}
}
int main()
{
cin >> n;
build(1, 1, n);
cin >> m;
for(int i = 1; i <= m; i++)
{
int l = read(), r = read();
printf("%d\n", ask(1, l, r).val);
}
return 0;
}
标签:取出 树节点 iostream str 题意 线段 函数 cin void
原文地址:https://www.cnblogs.com/BigYellowDog/p/11792938.html