来怒做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 系列的更多相关文章

  1. spoj GSS系列简要题解

    文章目录 GSS1 GSS2 GSS3 GSS4 GSS5 GSS6 GSS7 GSS8 传送门 这个GSSGSSGSS系列全部是跟子段有关的数据结构菜题. 于是来水一篇博客. GSS1 传送门 题意 ...

  2. SPOJ GSS系列

    众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...

  3. SPOJ GSS系列(数据结构维护技巧入门)

    题目链接 GSS $GSS1$ 对于每个询问$l$, $r$,查询$a_{l}$, $a_{l+1}$, $a_{l+2}$, ..., $a_{r}$这个序列的最大字段和. 建立线段树,每个节点维护 ...

  4. 【SPOJ GSS】数据结构题选做

    SPOJ GSS1 题意:给一个序列以及一些询问,每个是问\([l,r]\)中最大连续子序列和是多少. 思路:这个问题是以下问题的基础. 我们考虑用线段树来解决这个问题. 首先我们来想想如果要求出最大 ...

  5. SPOJ GSS(Can you answer the Queries)系列 7/8

    GSS1 线段树最大子段和裸题,不带修改,注意pushup. 然而并不会猫树之类的东西 #include<bits/stdc++.h> #define MAXN 50001 using n ...

  6. SPOJ QTREE 系列解题报告

    题目一 : SPOJ 375 Query On a Tree http://www.spoj.com/problems/QTREE/ 给一个树,求a,b路径上最大边权,或者修改a,b边权为t. #in ...

  7. SPOJ GSS

    GSS1 题目大意:给出一个数列,多次询问区间最长连续子段和 题解:线段树维护区间最长连续子段和gss,区间从最左元素开始的最长连续子段和lgss 区间以最右元素为结尾的最长连续子段和rgss以及区间 ...

  8. GSS 系列题解

    GSS GSS1 随便猫树或者线段树,就可以过了 猫树不说,线段树可以维护左边最大,右边最大,区间最大,区间值然后就做出来了. //Isaunoya #pragma GCC optimize(2) # ...

  9. 激!GSS系列

    #include <cstdio> ; ; inline int max(int, int); inline int getint(); inline void putint(int); ...

随机推荐

  1. POJ_3279_(dfs)(状态)

    ---恢复内容开始--- Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8219   Accepted:  ...

  2. Resetting the SMC & PRAM

    Resetting the SMC & PRAM on portables with a battery you should not remove on your own 1. Shut d ...

  3. windows 设置注册表服务自动启动

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\xxx\Start = ,=自动,,=禁用

  4. privot函数使用

    语法: table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) 将列转化为行 写个小示例 : ...

  5. Spring Boot 集成 JWT 实现单点登录授权

    使用步骤如下:1. 添加Gradle依赖: dependencies { implementation 'com.auth0:java-jwt:3.3.0' implementation('org.s ...

  6. 【LeetCode】4、Median of Two Sorted Arrays

    题目等级:Hard 题目描述:   There are two sorted arrays nums1 and nums2 of size m and n respectively.   Find t ...

  7. 优化JAVA查询Mongodb数量过大,查询熟读慢的方法

    前言:2018年的时候优化了一个项目,该项目从MOngodb中获取数据的时候一次去十万百万千万的数据过慢,往往每次都要二十秒,三十秒,今天提出了一个代码优化的方案 项目查从mongodb中获取数据:代 ...

  8. 00.不规则json序列化使用eval、demjson

    有下面一段字符串 import json str0 = '[{"name":"白云大道营业厅","siteaddr":"x...& ...

  9. 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 ...

  10. docker的容器可视化工具portainer

    1.搜索镜像 [root@holly ~]# docker search portainer 2.下载portainer [root@holly ~]# docker pull portainer/p ...