SPOJ GSS3 单点修改+区间最大子段和
Posted Allorkiya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ GSS3 单点修改+区间最大子段和相关的知识,希望对你有一定的参考价值。
题目大意
给定一个序列,需要支持单修和区间最大子段和,\\(n \\leq 50000\\)。
思路
一个序列的最大字段和可能出现在左半侧最大子段和,右半侧最大子段和和跨越两边的最大子段和。
维护四个标记:mxsum,mxpre,mxsuf,sum
,线段树操作即可。
有一个细节,查询的时候不能直接用左右孩子的最大后缀/前缀,因为查询的区间可能小于最大子段和出现的区间。
两种解决办法:
- 记录最大子段和出现的位置,维护的时候判断边界
- 将尽可能多的信息传递上来,用于计算。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
struct node
int l,r;
int mxsum;
int mxsuf;
int mxpre;
int sum;
;
int a[N];
struct segment_tree
node t[N << 2];
void update(int rt)
int ch = rt << 1;
t[rt].sum = t[ch].sum + t[ch + 1].sum;
t[rt].mxsum = max(max(t[ch].mxsum,t[ch + 1].mxsum),t[ch].mxsuf + t[ch + 1].mxpre);
t[rt].mxpre = max(t[ch].mxpre,t[ch].sum + t[ch + 1].mxpre);
t[rt].mxsuf = max(t[ch + 1].mxsuf,t[ch + 1].sum + t[ch].mxsuf);
void build(int l,int r,int rt)
t[rt].l = l;
t[rt].r = r;
if(l == r)
t[rt].sum = t[rt].mxsuf = t[rt].mxpre = t[rt].mxsum = a[l];
return;
int mid = (l + r) >> 1;
int ch = rt << 1;
build(l,mid,ch);
build(mid + 1,r,ch + 1);
update(rt);
void modify(int rt,int pos,int v)
if(t[rt].l == t[rt].r)
t[rt].sum = v;
t[rt].mxsum = v;
t[rt].mxpre = v;
t[rt].mxsuf = v;
return;
int mid = (t[rt].l + t[rt].r) >> 1;
int ch = rt << 1;
if(pos <= mid)
modify(ch,pos,v);
else
modify(ch + 1,pos,v);
update(rt);
node query (int l,int r,int rt)
if(l == t[rt].l and r == t[rt].r)
return t[rt];
int mid = (t[rt].l + t[rt].r) >> 1;
int ch = rt << 1;
if(r <= mid)
return query(l,r,ch);
else if(l > mid)
return query(l,r,ch + 1);
else
node ret1 = query(l,mid,ch);
node ret2 = query(mid + 1,r,ch + 1);
node res;
res.sum = ret1.sum + ret2.sum;
res.mxsum = max(max(ret1.mxsum,ret2.mxsum),ret1.mxsuf + ret2.mxpre);
res.mxpre = max(ret1.mxpre,ret1.sum + ret2.mxpre);
res.mxsuf = max(ret2.mxsuf,ret2.sum + ret1.mxsuf);
return res;
ST;
int n,q;
int main ()
cin >> n;
for(int i = 1;i <= n; i ++)
cin >> a[i];
ST.build(1,n,1);
cin >> q;
while(q --)
int op,l,r;
cin >> op >> l >> r;
if(op == 0)
ST.modify(1,l,r);
else
cout << ST.query(l,r,1).mxsum << endl;
return 0;
以上是关于SPOJ GSS3 单点修改+区间最大子段和的主要内容,如果未能解决你的问题,请参考以下文章
SP1716 GSS3 - Can you answer these queries III
$SP1716$ $GSS3$ $-$ $Can$ $you$ $answer$ $these$ $queries$ $III$