SPOJ GSS 系列
来怒做GSS系列了;
GSS1:https://www.luogu.org/problemnew/show/SP1043
这题就是维护一个 sum , mx , lmx , rmx,转移时用结构体就好了。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const maxn=;
int n,m,a[maxn];
struct N{
int sum,mx,lmx,rmx;
}t[maxn<<];
void pushup(int x)
{
int ls=(x<<),rs=(x<<|);
t[x].sum=t[ls].sum+t[rs].sum;
t[x].lmx=max(t[ls].lmx,t[ls].sum+t[rs].lmx);
t[x].rmx=max(t[rs].rmx,t[rs].sum+t[ls].rmx);
t[x].mx=max(t[x].sum,max(t[x].lmx,t[x].rmx));
t[x].mx=max(t[x].mx,max(t[ls].mx,t[rs].mx));
t[x].mx=max(t[x].mx,t[ls].rmx+t[rs].lmx);
}
N merge(N l,N r)
{
N ret;
ret.sum=l.sum+r.sum;
ret.lmx=max(l.lmx,l.sum+r.lmx);
ret.rmx=max(r.rmx,r.sum+l.rmx);
ret.mx=max(ret.sum,max(ret.lmx,ret.rmx));
ret.mx=max(ret.mx,max(l.mx,r.mx));
ret.mx=max(ret.mx,l.rmx+r.lmx);
return ret;
}
void build(int x,int l,int r)
{
if(l==r){t[x].mx=t[x].lmx=t[x].rmx=t[x].sum=a[l]; return;}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
N query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x];
int mid=((l+r)>>);
if(mid<L)return query(x<<|,mid+,r,L,R);
else if(mid>=R)return query(x<<,l,mid,L,R);
else return merge(query(x<<,l,mid,L,R),query(x<<|,mid+,r,L,R));
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
build(,,n);
scanf("%d",&m);
for(int i=,x,y;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",query(,,n,x,y).mx);
}
return ;
}
GSS2:https://www.luogu.org/problemnew/show/SP1557
突然好难,不会做了...
看了半天TJ,还是云里雾里...可能是对最大连续子段和的知识太不熟悉了;
大概就是要离线,把询问按右端点排序,然后逐个加点;
因为要去重,所以新加入一个点,影响到的左端点的区间只在上一个这个值出现的位置之后,于是可以用线段树做;
线段树叶子节点上的值表示以这个点为左端点、当前节点(i)为右端点的各种值;
sum 是不断累加的和,his 是历史上的最大值,也是查询的答案;
因为是线段树,所以要考虑一下标记,区分成不断累加的标记 tag 和历史上的最大增量 htg;
pushdown 的转移有点复杂,要注意顺序;
还是感觉好难想(其实是套路?)好难写啊...
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=1e5+;
int n,m,a[maxn],pre[maxn],lst[maxn<<];
ll ans[maxn];
struct N{
ll sum,his,tag,htg;
N(){sum=his=tag=htg=;}
}t[maxn<<];
struct Q{int l,r,bh;}q[maxn];
bool cmp(Q x,Q y){return x.r<y.r;}
N merge(N l,N r)
{
N ret;
ret.sum=max(l.sum,r.sum);
ret.his=max(l.his,r.his);
return ret;
}
void pushup(int x){t[x]=merge(t[x<<],t[x<<|]);}
void pushdown(int x)
{
int ls=(x<<),rs=(x<<|);
t[ls].his=max(t[ls].his,t[ls].sum+t[x].htg);
t[rs].his=max(t[rs].his,t[rs].sum+t[x].htg);
t[ls].sum+=t[x].tag;
t[rs].sum+=t[x].tag;
t[ls].htg=max(t[ls].htg,t[ls].tag+t[x].htg);
t[rs].htg=max(t[rs].htg,t[rs].tag+t[x].htg);
t[ls].tag+=t[x].tag;
t[rs].tag+=t[x].tag;
t[x].tag=; t[x].htg=;
}
void insert(int x,int l,int r,int L,int R,int val)
{
if(l>=L&&r<=R)
{
t[x].sum+=val;
t[x].his=max(t[x].his,t[x].sum);
t[x].tag+=val;
t[x].htg=max(t[x].htg,t[x].tag);
return;
}
pushdown(x);
int mid=((l+r)>>);
if(mid>=L)insert(x<<,l,mid,L,R,val);
if(mid<R)insert(x<<|,mid+,r,L,R,val);
pushup(x);
}
N query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x];
pushdown(x);
int mid=((l+r)>>);
if(mid<L)return query(x<<|,mid+,r,L,R);
else if(mid>=R)return query(x<<,l,mid,L,R);
else return merge(query(x<<,l,mid,L,R),query(x<<|,mid+,r,L,R));
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
pre[i]=lst[a[i]+maxn];
lst[a[i]+maxn]=i;
}
scanf("%d",&m);
for(int i=;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].bh=i;
sort(q+,q+m+,cmp);
for(int i=,j=;i<=n;i++)
{
insert(,,n,pre[i]+,i,a[i]);
while(q[j].r<=i&&j<=m)ans[q[j].bh]=query(,,n,q[j].l,q[j].r).his,j++;
}
for(int i=;i<=m;i++)printf("%lld\n",ans[i]);
return ;
}
GSS3:https://www.luogu.org/problemnew/show/SP1716
GSS1加修改。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const maxn=;
int n,m,a[maxn];
struct N{
int sum,mx,lmx,rmx;
}t[maxn<<];
void pushup(int x)
{
int ls=(x<<),rs=(x<<|);
t[x].sum=t[ls].sum+t[rs].sum;
t[x].lmx=max(t[ls].lmx,t[ls].sum+t[rs].lmx);
t[x].rmx=max(t[rs].rmx,t[rs].sum+t[ls].rmx);
t[x].mx=max(t[x].sum,max(t[x].lmx,t[x].rmx));
t[x].mx=max(t[x].mx,max(t[ls].mx,t[rs].mx));
t[x].mx=max(t[x].mx,t[ls].rmx+t[rs].lmx);
}
N merge(N l,N r)
{
N ret;
ret.sum=l.sum+r.sum;
ret.lmx=max(l.lmx,l.sum+r.lmx);
ret.rmx=max(r.rmx,r.sum+l.rmx);
ret.mx=max(ret.sum,max(ret.lmx,ret.rmx));
ret.mx=max(ret.mx,max(l.mx,r.mx));
ret.mx=max(ret.mx,l.rmx+r.lmx);
return ret;
}
void build(int x,int l,int r)
{
if(l==r){t[x].mx=t[x].lmx=t[x].rmx=t[x].sum=a[l]; return;}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
N query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x];
int mid=((l+r)>>);
if(mid<L)return query(x<<|,mid+,r,L,R);
else if(mid>=R)return query(x<<,l,mid,L,R);
else return merge(query(x<<,l,mid,L,R),query(x<<|,mid+,r,L,R));
}
void update(int x,int l,int r,int pos,int val)
{
if(l==r){t[x].mx=t[x].lmx=t[x].rmx=t[x].sum=val; return;}
int mid=((l+r)>>);
if(pos<=mid)update(x<<,l,mid,pos,val);
else update(x<<|,mid+,r,pos,val);
pushup(x);
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
build(,,n);
scanf("%d",&m);
for(int i=,op,x,y;i<=m;i++)
{
scanf("%d%d%d",&op,&x,&y);
if(op==)update(,,n,x,y);
if(op==)printf("%d\n",query(,,n,x,y).mx);
}
return ;
}
GSS4:https://www.luogu.org/problemnew/show/SP2713
由于一个数开方几次就到1了,所以对于一个全是1的区间就不用去修改了。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int const maxn=1e5+;
int n,m,u;
ll a[maxn],sum[maxn<<];
void build(int x,int l,int r)
{
if(l==r){sum[x]=a[l]; return;}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
sum[x]=sum[x<<]+sum[x<<|];
}
void update(int x,int l,int r,int L,int R)
{
if(sum[x]==r-l+)return;
if(l==r){sum[x]=sqrt(sum[x]); return;}
int mid=((l+r)>>);
if(L<=mid)update(x<<,l,mid,L,R);
if(R>mid) update(x<<|,mid+,r,L,R);
sum[x]=sum[x<<]+sum[x<<|];
}
ll query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return sum[x];
int mid=((l+r)>>); ll ret=;
if(mid>=L)ret+=query(x<<,l,mid,L,R);
if(mid<R)ret+=query(x<<|,mid+,r,L,R);
return ret;
}
int main()
{
while(~scanf("%d",&n))
{
printf("Case #%d:\n",++u);
for(int i=;i<=n;i++)scanf("%lld",&a[i]);
build(,,n);
scanf("%d",&m);
for(int i=,op,x,y;i<=m;i++)
{
scanf("%d%d%d",&op,&x,&y);
if(x>y)swap(x,y);
if(op==)update(,,n,x,y);
if(op==)printf("%lld\n",query(,,n,x,y));
}
printf("\n");
}
return ;
}
GSS5:https://www.luogu.org/problemnew/show/SP2916
分类讨论,不相交或相交;
相交分穿过 x2,或穿过 y1,或在 x2 和 y1 中间;
细节有点神奇,注释那里要注意一下,因为如果是 x1,x2,那么实际还是没有摆脱 x2,所以不行(?);
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const maxn=1e5+,inf=1e9;
int T,n,m,a[maxn];
struct N{
int sum,mx,lmx,rmx;
N(){sum=mx=lmx=rmx=;}
}t[maxn<<];
void pushup(int x)
{
int ls=(x<<),rs=(x<<|);
t[x].sum=t[ls].sum+t[rs].sum;
t[x].lmx=max(t[ls].lmx,t[ls].sum+t[rs].lmx);
t[x].rmx=max(t[rs].rmx,t[rs].sum+t[ls].rmx);
t[x].mx=max(t[ls].rmx+t[rs].lmx,max(t[ls].mx,t[rs].mx));
}
N merge(N l,N r)
{
N ret;
ret.sum=l.sum+r.sum;
ret.lmx=max(l.lmx,l.sum+r.lmx);
ret.rmx=max(r.rmx,r.sum+l.rmx);
ret.mx=max(l.rmx+r.lmx,max(l.mx,r.mx));
return ret;
}
void build(int x,int l,int r)
{
if(l==r){t[x].sum=t[x].mx=t[x].lmx=t[x].rmx=a[l]; return;}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
N query(int x,int l,int r,int L,int R)
{
N ret;
if(L>R)return ret;
if(l>=L&&r<=R)return t[x];
int mid=((l+r)>>);
if(mid<L)return query(x<<|,mid+,r,L,R);
else if(mid>=R)return query(x<<,l,mid,L,R);
else return merge(query(x<<,l,mid,L,R),query(x<<|,mid+,r,L,R));
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
build(,,n);
scanf("%d",&m);
for(int i=,x1,y1,x2,y2;i<=m;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(y1<x2)
{
N ls=query(,,n,x1,y1),rs=query(,,n,x2,y2),mid=query(,,n,y1+,x2-);
printf("%d\n",ls.rmx+mid.sum+rs.lmx);
}
else
{
int ans=-inf;
N ls=query(,,n,x1,x2-),rs=query(,,n,x2,y2);//不能是 x1,x2 和 x2+1,y2?
ans=max(ans,ls.rmx+rs.lmx);
ls=query(,,n,x1,y1),rs=query(,,n,y1+,y2);
ans=max(ans,ls.rmx+rs.lmx);
ls=query(,,n,x2,y1);
ans=max(ans,ls.mx);
printf("%d\n",ans);
}
}
}
return ;
}
(待更)
SPOJ GSS 系列的更多相关文章
- 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 GSS】数据结构题选做
SPOJ GSS1 题意:给一个序列以及一些询问,每个是问\([l,r]\)中最大连续子序列和是多少. 思路:这个问题是以下问题的基础. 我们考虑用线段树来解决这个问题. 首先我们来想想如果要求出最大 ...
- SPOJ GSS(Can you answer the Queries)系列 7/8
GSS1 线段树最大子段和裸题,不带修改,注意pushup. 然而并不会猫树之类的东西 #include<bits/stdc++.h> #define MAXN 50001 using n ...
- SPOJ QTREE 系列解题报告
题目一 : SPOJ 375 Query On a Tree http://www.spoj.com/problems/QTREE/ 给一个树,求a,b路径上最大边权,或者修改a,b边权为t. #in ...
- SPOJ GSS
GSS1 题目大意:给出一个数列,多次询问区间最长连续子段和 题解:线段树维护区间最长连续子段和gss,区间从最左元素开始的最长连续子段和lgss 区间以最右元素为结尾的最长连续子段和rgss以及区间 ...
- GSS 系列题解
GSS GSS1 随便猫树或者线段树,就可以过了 猫树不说,线段树可以维护左边最大,右边最大,区间最大,区间值然后就做出来了. //Isaunoya #pragma GCC optimize(2) # ...
- 激!GSS系列
#include <cstdio> ; ; inline int max(int, int); inline int getint(); inline void putint(int); ...
随机推荐
- python 模块学习——time模块
Python语言中与时间有关的模块主要是:time,datetime,calendar time模块中的大多数函数是调用了所在平台C library的同名函数, 所以要特别注意有些函数是平台相关的,可 ...
- CAD设置图层亮度(com接口)
主要用到函数说明: MxDrawXCustomFunction::Mx_SetLayerBright 设置显示亮度,默认值为100%.详细说明如下: 参数 说明 LPCTSTR pszLayerNam ...
- 快速搭建vue2.0+boostrap项目
一.Vue CLI初始化Vue项目 全局安装vue cli npm install --global vue-cli 创建一个基于 webpack 模板的新项目 vue init webpack my ...
- LINQ简记(3):子句
LINQ查询表达式的子句如select,where,from等都是比较简单的子句,相信各位多练习练习,再结合MSDN的例子,基本上是可以理解的,因此,本文只挑几个有代表性的,以及有些难理解的子句来简述 ...
- 【6】Django视图函数
治大国若烹小鲜.以道莅天下 --老子<道德经> 本节内容 Django web项目的运行流程分析 视图处理函数的定义 多视图处理函数及接收参数 1. web项目运行流程分析 通常情况下,完 ...
- BFOA
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> ...
- BZOJ 1232 USACO 2008 Nov. 安慰奶牛Cheer
[题解] 对于每一条边,我们通过它需要花费的代价是边权的两倍加上这条边两个端点的点权. 我们把每条边的边权设为上述的值,然后跑一边最小生成树,再把答案加上最小的点权就好了. #include<c ...
- 关于wordclou的一些简单操作
详细讲解一下怎么用python的三方库wordcloud制作一个关于歌曲<Vincent>的歌词,有特别背景的云词效果,如图所示: 首先的先准备好一张背景图,为了云词效果,可以实现修改一下 ...
- hdu 3605 最大流sap+二进制思想(啊啊)
/*因为n非常大如果正常建边的话会超内存,每种状态的数目共2--10种状状体记录起来,源点与状态建边权值为状态数,状态与星球建边,星球与汇点建边*/ #include<stdio.h> # ...
- springCloud学习-断路器(Hystrix)
1.问题分析 在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用.为了保证其高 ...