1.GSS系列问题
是 s p o j spoj spoj上的一组数据结构问题
通常是查询最大子段和
找到这组题还是要感谢 a k i o i akioi akioi的 g j m gjm gjm
G S S = G r e a t e s t S u m s o f S u b s e g m e n t s GSS=Greatest\ Sums \ of \ Subsegments GSS=Greatest Sums of Subsegments
这里是按我洛谷认为的难度顺序排序的
c o n t i n u e u p d a t i n g . . . . . . continue\ updating...... continue updating......
2.GSS1
GSS系列第一题传送门
纯粹的维护最大子段和
怎么做呢?
我们考虑,在合并两颗子树的时候,最大子段和会在哪一部分
1.在左子树内=> u . a n s = l s o n . a n s u.ans=lson.ans u.ans=lson.ans
2.在右子树内=> u . a n s = r s o n . a n s u.ans=rson.ans u.ans=rson.ans
3.在中间=> u . a n s = l s o n . l m a x + r s o n . l m a x u.ans=lson.lmax+rson.lmax u.ans=lson.lmax+rson.lmax
其中 l m a x lmax lmax表示最大前缀和, r m a x rmax rmax表示最大后缀和
那么我们考虑最大前缀和和最大后缀和怎么确定
以最大前缀和为例
1.左子树的最大前缀和=> u . l m a x = l s o n . l m a x u.lmax=lson.lmax u.lmax=lson.lmax
2.左子树+右子树的最大前缀和=> u . l m a x = l s o n . s u m + r s o n . l m a x u.lmax=lson.sum+rson.lmax u.lmax=lson.sum+rson.lmax
其中 s u m sum sum表示区间和
然后就没了
# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <ctime>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=1e5+5;
const int inf=0x7fffffff;
const double eps=1e-7;
template <typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,m;
int a[N];
struct segment_tree{
int sumf,sumb;
int sum;
int ans;
int l,r;
}seg[N<<2];
# define lc (u<<1)
# define rc (u<<1|1)
void pushup(int u){
seg[u].sumf=max(seg[lc].sumf,seg[lc].sum+seg[rc].sumf);
seg[u].sumb=max(seg[rc].sumb,seg[rc].sum+seg[lc].sumb);
seg[u].sum=seg[lc].sum+seg[rc].sum;
seg[u].ans=max(max(seg[lc].ans,seg[rc].ans),seg[lc].sumb+seg[rc].sumf);
}
void build(int u,int l,int r){
seg[u].l=l,seg[u].r=r;
if(l==r){
seg[u].sumf=seg[u].sumb=seg[u].sum=seg[u].ans=a[l];return;}
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(u);
}
segment_tree query(int u,int l,int r){
if(seg[u].l>=l&&seg[u].r<=r)return seg[u];
int mid=seg[u].l+seg[u].r>>1;
if(r<=mid)return query(lc,l,r);
if(l>mid)return query(rc,l,r);
segment_tree ls=query(lc,l,r),rs=query(rc,l,r),res;
res.sumf=max(ls.sumf,ls.sum+rs.sumf);
res.sumb=max(rs.sumb,rs.sum+ls.sumb);
res.sum=ls.sum+rs.sum;
res.ans=max(max(ls.ans,rs.ans),ls.sumb+rs.sumf);
return res;
}
int main()
{
read(n);
Rep(i,1,n)read(a[i]);
build(1,1,n);
read(m);
Rep(i,1,m){
int l,r;
read(l),read(r);
printf("%d\n",query(1,l,r).ans);
}
return 0;
}
3.GSS3
传送门
这道题跟上一个没啥区别…
加一个 u p d a t e update update就好了
对了,这题可以算三倍经验
算上GSS1,还有一道小白逛公园
# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <ctime>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=1e5+5;
const int inf=0x7fffffff;
const double eps=1e-7;
template <typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,m;
int a[N];
struct segment_tree{
int sumf,sumb;
int sum;
int ans;
int l,r;
}seg[N<<2];
# define lc (u<<1)
# define rc (u<<1|1)
void pushup(int u){
seg[u].sumf=max(seg[lc].sumf,seg[lc].sum+seg[rc].sumf);
seg[u].sumb=max(seg[rc].sumb,seg[rc].sum+seg[lc].sumb);
seg[u].sum=seg[lc].sum+seg[rc].sum;
seg[u].ans=max(max(seg[lc].ans,seg[rc].ans),seg[lc].sumb+seg[rc].sumf);
}
void build(int u,int l,int r){
seg[u].l=l,seg[u].r=r;
if(l==r){
seg[u].sumf=seg[u].sumb=seg[u].sum=seg[u].ans=a[l];return;}
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(u);
}
void update(int u,int x,int k){
if(seg[u].l==seg[u].r){
seg[u].sumf=seg[u].sumb=seg[u].sum=seg[u].ans=k;return;}
int mid=seg[u].l+seg[u].r>>1;
if(x<=mid)update(lc,x,k);
else update(rc,x,k);
pushup(u);
}
segment_tree query(int u,int l,int r){
if(seg[u].l>=l&&seg[u].r<=r)return seg[u];
int mid=seg[u].l+seg[u].r>>1;
if(r<=mid)return query(lc,l,r);
if(l>mid)return query(rc,l,r);
segment_tree ls=query(lc,l,r),rs=query(rc,l,r),res;
res.sumf=max(ls.sumf,ls.sum+rs.sumf);
res.sumb=max(rs.sumb,rs.sum+ls.sumb);
res.sum=ls.sum+rs.sum;
res.ans=max(max(ls.ans,rs.ans),ls.sumb+rs.sumf);
return res;
}
int main()
{
read(n);
Rep(i,1,n)read(a[i]);
build