GSS系列(1)——GSS1&&GSS3
题意:询问一个区间内的最大连续子段和(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的更多相关文章
- spoj gss1 gss3
传送门 gss1 gss3 spoj gss系列=最大字段和套餐 gss1就是gss3的无单点修改版 有区间查询和单点修改,考虑用线段树维护 我们要维护区间权值和\(s\),区间最大前缀和\(xl\) ...
- SPOJ GSS 系列
来怒做GSS系列了: GSS1:https://www.luogu.org/problemnew/show/SP1043 这题就是维护一个 sum , mx , lmx , rmx,转移时用结构体就好 ...
- spoj GSS系列简要题解
文章目录 GSS1 GSS2 GSS3 GSS4 GSS5 GSS6 GSS7 GSS8 传送门 这个GSSGSSGSS系列全部是跟子段有关的数据结构菜题. 于是来水一篇博客. GSS1 传送门 题意 ...
- SPOJ GSS系列
众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...
- SPOJ GSS系列(数据结构维护技巧入门)
题目链接 GSS $GSS1$ 对于每个询问$l$, $r$,查询$a_{l}$, $a_{l+1}$, $a_{l+2}$, ..., $a_{r}$这个序列的最大字段和. 建立线段树,每个节点维护 ...
- SPOJ - GSS1&&GSS3
GSS1 #include<cstdio> #include<iostream> #define lc k<<1 #define rc k<<1|1 u ...
- GSS 系列题解
GSS GSS1 随便猫树或者线段树,就可以过了 猫树不说,线段树可以维护左边最大,右边最大,区间最大,区间值然后就做出来了. //Isaunoya #pragma GCC optimize(2) # ...
- 激!GSS系列
#include <cstdio> ; ; inline int max(int, int); inline int getint(); inline void putint(int); ...
- SPOJ GSS1 && GSS3 (无更新/更新单点,并询问区间最大连续和)
http://www.spoj.com/problems/GSS1/ 题意:无更新询问区间最大连续和. 做法:线段树每个节点维护sum[rt],maxsum[rt],lsum[rt],rsum[rt] ...
随机推荐
- reverse array java
/* package whatever; // don't place package name! */ import java.util.*; import java.lang.*; import ...
- 解决eclipse+MAVEN提示One or more constraints have not been satisfied.的问题
应用版本:eclipse luna4.4.1 JDK:1.8 Maven:3.2.5 问题现象: 1.编译工程后总该是显示下面两个错误: One or more constraints have no ...
- Vmware虚拟机
1.在虚拟机安装完系统后找到相对应的保存路径如:D:\VMware\VOS\Win7x64OS 2.该目录下面会有很多文件和文件夹,其中配置文件Windows 7 x64.vmx和硬盘文件Window ...
- 03-VTK基础概念(2)
3.3 光照 剧场里有各式各样的灯光,三维渲染场景中也一样,可以有多个光照存在.光照和相机是三维渲染场景必备的因素,如果没有指定(像3.1.1_RenderCylinder例子,我们没有给Render ...
- 【OpenStack】OpenStack系列5之Cinder详解
源码下载安装 git clone -b stable/icehouse https://github.com/openstack/cinder.git pip install -r requireme ...
- 3Sum Closest & 3Sum Smaller
Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...
- mysql varchar
2013年9月13日 14:58:43 MYSQL的varchar数据类型 先说结论: 如果设置字段长度为30,字符编码为utf8,那么一个汉字算一个字符,一个数字算一个字符,一个字母也算一个字符 版 ...
- Java for LeetCode 201 Bitwise AND of Numbers Range
Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers ...
- DP:炮兵阵地问题(POJ 1185)
正确的打炮方式(大雾)(点我查看) 2015-08-21 问题是中文的,大家可以进去看看. 先说一个坑,这个问题我交了很多次,都没过,反正是WA到我烦了,都不知道哪里错了!!!怎么会有错,然后翻了一下 ...
- Maven运行时异常java.lang.UnsupportedClassVersionError的解决方案
我用的Maven版本为最新版:3.3.9,但是我执行一个简单的clean命令会报如下错误: Exception in thread "main" java.lang.Unsuppo ...