来怒做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. Angular——自定义指令

    基本介绍 有了很多内置指令,但是依然无法满足我们的需要,我们可以自己定义一个指令,实现默写功能. 基本使用 directive方法可以帮助我们自己定义一个指令,它的返回方式一共有四种,ECMA,代表所 ...

  2. 移动web——touch事件介绍

    基本概念 1.在移动web端点击事件或者滑动屏幕.捏合等动作都是由touchstar.touchmove.touchend这三个事件组合在一起使用的 2.click事件在移动端会有0.2秒的延迟,下面 ...

  3. 删除ListView item数据 页面不刷新

    最近碰到一个匪夷所思的事情.就是我删除listView中一条item数据  网络请求成功了 但是页面不成功,一番折腾 ,找到问题 ,原来我给item 添加了北京点击事假,又给listView 被禁设置 ...

  4. Centos 编译安装Haproxy

    一.环境介绍 1.Centos6 2. haproxy-1.4.25.tar.gz 二.安装 $ curl -O http://haproxy.1wt.eu/download/1.4/src/hapr ...

  5. CSS (层叠样式表)

    层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言.CSS不仅可以静态 ...

  6. C/C++ 之dll注入

    #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <time.h> ...

  7. Mock随机生成数据模拟后台接口

    <html> <head> <title>测试</title> <script src="http://code.jquery.com/ ...

  8. 多目标跟踪笔记一:Finding the Best Set of K Paths Through a Trellis With Application to Multitarget Tracking

    Abstract 本文提出一种寻找K最优路径的方法. k最优路径的定义:1.the sum of the metrics of all k paths in the set is minimized. ...

  9. codevs 1160 蛇形矩阵

    1160 蛇形矩阵 传送门  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解       题目描述 Description 小明玩一个数字游戏,取个n行 ...

  10. OI数学知识清单

    OI常用的数学知识总结 本文持续更新…… 总结一下OI中的玄学知识 先列个单子,(from秦神 数论 模意义下的基本运算和欧拉定理 筛素数和判定素数欧几里得算法及其扩展[finish] 数论函数和莫比 ...