题意:询问一个区间内的最大连续子段和(GSS1),并且有单点修改的操作(GSS2)。

思路:这个题目在老人家的大白鼠里出现过,不过那个是求两个下标,并且相同取更小值。——传的东西更多,判断也稍微繁琐一些。。。

考虑我们平时如何处理最大连续子段和——O(n)DP,然而显然在一个时刻会修改的序列上无法实现。我们至少需要一个O(nlgn)的算法。考虑到这种连续的和可以对应线段树的一些操作,我们就将它应用到线段树上。

老人家在讲子段和的时候提供了一种分治算法——如果将一段序列分成两端,那么它的最大子段和要么完全出现在左边,要么完全出现在右边,要么横跨中点。那么我们可以将线段树维护这么几个状态——这段序列最大前缀(即一定包括序列头),最大后缀(一定包括序列尾),中间最大值(没有什么限制),整段序列和。

对于每一段序列,如何处理它的最大值呢?

在线段树中左右两个儿子分别代表了左序列与右序列,那么构成这个序列最大子序列和要么是左序列的最大要么是右序列的最大要么值左序列后缀加上右序列的前缀——三个判断分别处理即可。(具体看代码

/*==========================================================================
# Last modified: 2016-02-02 15:50
# Filename: GSS1.cpp
# Description:
==========================================================================*/
#define me AcrossTheSky
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> #include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#define lowbit(x) (x)&(-x)
#define INF 1000000000
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define maxn 100000
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
/*==================split line==================*/
struct interval{
int sub,sum,suf,pre,v;
}tree[maxn*3];
int L,R,q,n,p;
int a[maxn];
void updata(int node,int l,int r){
if (l==r) {
int x=p;
tree[node].v=x; tree[node].sub=x;
tree[node].pre=x; tree[node].suf=x;
tree[node].sum=x;
return;
}
int mid=rs(l,r),lc=ls(node,0),rc=lc|1;
if (q<=mid) updata(lc,l,mid);
else updata(rc,mid+1,r);
tree[node].sum=tree[lc].sum+tree[rc].sum;
tree[node].pre=max(tree[lc].pre,tree[lc].sum+tree[rc].pre);
tree[node].suf=max(tree[rc].suf,tree[rc].sum+tree[lc].suf); tree[node].sub=max(tree[lc].sub,tree[rc].sub);
tree[node].sub=max(tree[node].sub,tree[lc].suf+tree[rc].pre);
}
void build_tree(int node,int l,int r){
if (l==r) {
int x=a[l];
tree[node].v=x; tree[node].sub=x;
tree[node].pre=x; tree[node].suf=x;
tree[node].sum=x;
return;
}
int mid=rs(l,r),lc=ls(node,0),rc=lc|1;
build_tree(lc,l,mid);build_tree(rc,mid+1,r);
tree[node].sum=tree[lc].sum+tree[rc].sum;
tree[node].pre=max(tree[lc].pre,tree[lc].sum+tree[rc].pre);
tree[node].suf=max(tree[rc].suf,tree[rc].sum+tree[lc].suf); tree[node].sub=max(tree[lc].sub,tree[rc].sub);
tree[node].sub=max(tree[node].sub,tree[lc].suf+tree[rc].pre);
}
void reset(interval &x){
x.sub=-INF; x.v=-INF; x.pre=-INF; x.suf=-INF; x.sum=-INF;
}
interval query(int node,int l,int r){
if (L<=l && r<=R) return tree[node];
int mid=rs(l,r),lc=ls(node,0),rc=lc|1;
interval x,y;
reset(x); reset(y);
x.sum=0; y.sum=0;
if (L<=mid) x=query(lc,l,mid);
if (R>mid) y=query(rc,mid+1,r);
interval ans;
reset(ans);
ans.sub=max(max(x.sub,y.sub),x.suf+y.pre);
ans.suf=max(y.suf,y.sum+x.suf);
ans.pre=max(x.pre,x.sum+y.pre);
ans.sum=x.sum+y.sum;
return ans;
}
int main(){
freopen("a.in","r",stdin);
memset(tree,0,sizeof(tree));
cin >> n;
FOR(q,1,n) scanf("%d",&a[q]);
build_tree(1,1,n);
int m; cin >> m;
FORP(i,1,m){
int t; scanf("%d",&t);
if (t==1){
scanf("%d%d",&L,&R);
printf("%d\n",query(1,1,n).sub);
}
else {
scanf("%d%d",&q,&p);
updata(1,1,n);
}
}
}

GSS系列(1)——GSS1&&GSS3的更多相关文章

  1. spoj gss1 gss3

    传送门 gss1 gss3 spoj gss系列=最大字段和套餐 gss1就是gss3的无单点修改版 有区间查询和单点修改,考虑用线段树维护 我们要维护区间权值和\(s\),区间最大前缀和\(xl\) ...

  2. SPOJ GSS 系列

    来怒做GSS系列了: GSS1:https://www.luogu.org/problemnew/show/SP1043 这题就是维护一个 sum , mx , lmx , rmx,转移时用结构体就好 ...

  3. spoj GSS系列简要题解

    文章目录 GSS1 GSS2 GSS3 GSS4 GSS5 GSS6 GSS7 GSS8 传送门 这个GSSGSSGSS系列全部是跟子段有关的数据结构菜题. 于是来水一篇博客. GSS1 传送门 题意 ...

  4. SPOJ GSS系列

    众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...

  5. SPOJ GSS系列(数据结构维护技巧入门)

    题目链接 GSS $GSS1$ 对于每个询问$l$, $r$,查询$a_{l}$, $a_{l+1}$, $a_{l+2}$, ..., $a_{r}$这个序列的最大字段和. 建立线段树,每个节点维护 ...

  6. SPOJ - GSS1&&GSS3

    GSS1 #include<cstdio> #include<iostream> #define lc k<<1 #define rc k<<1|1 u ...

  7. GSS 系列题解

    GSS GSS1 随便猫树或者线段树,就可以过了 猫树不说,线段树可以维护左边最大,右边最大,区间最大,区间值然后就做出来了. //Isaunoya #pragma GCC optimize(2) # ...

  8. 激!GSS系列

    #include <cstdio> ; ; inline int max(int, int); inline int getint(); inline void putint(int); ...

  9. SPOJ GSS1 && GSS3 (无更新/更新单点,并询问区间最大连续和)

    http://www.spoj.com/problems/GSS1/ 题意:无更新询问区间最大连续和. 做法:线段树每个节点维护sum[rt],maxsum[rt],lsum[rt],rsum[rt] ...

随机推荐

  1. RAID阵列的初始化与管理

    如果我们创建RAID阵列的目的是新部署一台服务器,我们建议所有新创建的RAID阵列都应该做初始化操作,这样,硬盘上原有的用户数据将被清除,以便进行后续的系统,软件安装. 转自: http://zh.c ...

  2. HTML模仿桌面

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. 【转】java反射详解

    转自:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html 本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的 ...

  4. iOS 利用self.navigationItem.backBarButtonItem修改后退按钮文字

    @property(nonatomic,retain) UIBarButtonItem *backBarButtonItem; // Bar button item to use for the ba ...

  5. TinyMCE textarea 输入框外部程序动态修改方法

    TinyMCE textarea 输入框外部程序动态修改方法 Public Function C2IE_TINYMCE(ByVal id As String, ByVal value As Strin ...

  6. codeforces 483C.Diverse Permutation 解题报告

    题目链接:http://codeforces.com/problemset/problem/483/C 题目意思:给出 n 和 k,要求输出一个含有 n 个数的排列 p1, p2, ...,pn,使得 ...

  7. 【读书笔记】读《JavaScript设计模式》之适配器模式

    一.定义 适配器模式可用来在现有接口和不兼容的类之间进行匹配.使用这种模式的对象又叫包装器(wrapper),因为它们是在用一个新的接口包装另一个对象.在设计类的时候旺旺会遇到有些接口不能与现有API ...

  8. 昨天晚上也弄不清楚是自己密码被盗了还是由于ip冲突

    所以还是尽量要相信自己所见到的,今天上午是安卓课程,说实话,昨天晚上都是2:30睡的,现在硬是要把时间待这么晚才回去睡,是因为我想尽快入睡,昨天晚上就是眼睛都有点睁不开了,所以就睡得很快,但是早上也是 ...

  9. Oracle 操作 - 配置

    http://blog.csdn.net/flyingbox/article/details/1823231 http://blog.csdn.net/libingquan008/article/de ...

  10. SVN服务器搭建和使用(二)(转载)

    转载地址:http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407979.html 上一篇介绍了VisualSVN Server和Torto ...