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] ...
随机推荐
- Mysql函数集合
Mysql提供了很多函数 提供的常用函数集合 一.数学函数 ABS(x) 返回x的绝对值 BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制) CEILING(x) 返回大于x的最小整 ...
- Linux LAMP环境搭建
什么是LAMP Linux+Apache+Mysql/MariaDB+Perl/PHP/Python一组常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被放在一起使用,拥有了 ...
- CPU tick counter
#define rdtscll(val) \ __asm__ __volatile__ ("rdtsc" : "=A" (val)) example #incl ...
- jquery博客收集的IE6中CSS常见BUG全集及解决方案
今天的样式调的纠结,一会这边一会那么把jquery博客折腾的头大,浏览器兼容性.晚上闲着收集一些常见IE6中的BUG 3像素问题及解决办法 当使用float浮动容器后,在IE6下会产生3px的空隙,有 ...
- 工作中常用shell之ssh登陆不用输入"yes"
ip="192.168.5.166"ssh $ip -o StrictHostKeyChecking=no //ssh登陆不用输入"yes" ...
- 【Python】Django 聚合 Count与Sum用法,注意点
代码示例: from django.db.models import Sum, Count #alarm_sum_group_items = models.FILE_PROTECT_ALARM.obj ...
- Gson简要使用
哇,原来我已经潜水2年多了,还是需要养成习惯写写东西啊. 最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. ...
- su成别的用户后仍以原来私钥访问远程机器
背景: 同步机和游戏服两台机都有个人用户账号和游戏账号xy1,游戏服设了xy1的ssh强制命令来受同步机的xy1控制.现在需要在同步机上用xy1进行一个控制游戏服的操作,该操作需要在同步机远程tail ...
- Android的Observable和iOS的NotificationCenter
使用起来很类似,参看以下网址http://stackoverflow.com/questions/10327200/equivalent-of-ios-nsnotificationcenter-in- ...
- Windows下配置Tomcat服务器
Tomcat服务器是Apache开源基金会的一个项目,tomcat不仅能作为静态文件的服务器,也可以作为JSP/Servlet的web容器,而且使用广泛,性能也不错,那么下面来配置一个基本的基于tom ...