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); ...
随机推荐
- POJ_3279_(dfs)(状态)
---恢复内容开始--- Fliptile Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8219 Accepted: ...
- Resetting the SMC & PRAM
Resetting the SMC & PRAM on portables with a battery you should not remove on your own 1. Shut d ...
- windows 设置注册表服务自动启动
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\xxx\Start = ,=自动,,=禁用
- privot函数使用
语法: table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) 将列转化为行 写个小示例 : ...
- Spring Boot 集成 JWT 实现单点登录授权
使用步骤如下:1. 添加Gradle依赖: dependencies { implementation 'com.auth0:java-jwt:3.3.0' implementation('org.s ...
- 【LeetCode】4、Median of Two Sorted Arrays
题目等级:Hard 题目描述: There are two sorted arrays nums1 and nums2 of size m and n respectively. Find t ...
- 优化JAVA查询Mongodb数量过大,查询熟读慢的方法
前言:2018年的时候优化了一个项目,该项目从MOngodb中获取数据的时候一次去十万百万千万的数据过慢,往往每次都要二十秒,三十秒,今天提出了一个代码优化的方案 项目查从mongodb中获取数据:代 ...
- 00.不规则json序列化使用eval、demjson
有下面一段字符串 import json str0 = '[{"name":"白云大道营业厅","siteaddr":"x...& ...
- PAT 1097. Deduplication on a Linked List (链表)
Given a singly linked list L with integer keys, you are supposed to remove the nodes with duplicated ...
- docker的容器可视化工具portainer
1.搜索镜像 [root@holly ~]# docker search portainer 2.下载portainer [root@holly ~]# docker pull portainer/p ...