【BZOJ2482】[Spoj1557] Can you answer these queries II 线段树
【BZOJ2482】[Spoj1557] Can you answer these queries II
Description
给定n个元素的序列。
给出m个询问:求l[i]~r[i]的最大子段和(可选空子段)。
这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次。
比如:1,2,3,2,2,2出现了3次,但只算一次,于是这个序列的和是1+2+3=6。
Input
第一行一个数n。
第二行n个数,为给定的序列,这些数的绝对值小于等于100000。
第三行一个数m。
接下来m行,每行两个数,l[i],r[i]。
Output
M行,每行一个数,为每个询问的答案。
Sample Input
4 -2 -2 3 -1 -4 2 2 -6
3
1 2
1 5
4 9
Sample Output
5
3
HINT
【数据说明】
30%:1 <= n, m <= 100
100%:1 <= n, m <= 100000
题解:还是考虑这点:每个子串都是某个前缀的后缀,所以我们依旧枚举每个前缀,用线段树维护它的所有后缀。
出现两次只算一次怎么办?只需要在扫到一个数的时候将它上一个出现的位置变成0即可,这样就会改边很多后缀的值,用线段树去维护。
但是本题求的是最大连续子段和啊,其实只需要维护每个后缀的历史最大值就可以了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,m;
int last[maxn<<1],pre[maxn],v[maxn];
ll ans[maxn];
struct node
{
ll t,ht,s,hs;
}s[maxn<<2];
struct QUERY
{
int l,r,org;
}q[maxn];
inline void phd(int x,int y)
{
if(y>0) s[x].hs=max(s[x].hs,s[x].s+y),s[x].ht=max(s[x].ht,s[x].t+y);
}
inline void pd(int x,int y)
{
s[x].s+=y,s[x].t+=y;
if(y>0) s[x].hs=max(s[x].hs,s[x].s),s[x].ht=max(s[x].ht,s[x].t);
}
inline void pushdown(int x)
{
if(s[x].ht) phd(lson,s[x].ht),phd(rson,s[x].ht),s[x].ht=0;
if(s[x].t) pd(lson,s[x].t),pd(rson,s[x].t),s[x].t=0;
}
inline void pushup(int x)
{
s[x].s=max(s[lson].s,s[rson].s),s[x].hs=max(s[lson].hs,s[rson].hs);
}
void updata(int l,int r,int x,int a,int b,int c)
{
if(a<=l&&r<=b)
{
pd(x,c);
return ;
}
pushdown(x);
int mid=(l+r)>>1;
if(a<=mid) updata(l,mid,lson,a,b,c);
if(b>mid) updata(mid+1,r,rson,a,b,c);
pushup(x);
}
ll query(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b) return s[x].hs;
pushdown(x);
int mid=(l+r)>>1;
if(b<=mid) return query(l,mid,lson,a,b);
if(a>mid) return query(mid+1,r,rson,a,b);
return max(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
}
bool cmp(const QUERY &a,const QUERY &b)
{
return a.r<b.r;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd();
int i,j;
for(i=1;i<=n;i++) v[i]=rd(),pre[i]=last[v[i]+100000],last[v[i]+100000]=i;
m=rd();
for(i=1;i<=m;i++) q[i].l=rd(),q[i].r=rd(),q[i].org=i;
sort(q+1,q+m+1,cmp);
for(i=j=1;i<=n;i++)
{
updata(1,n,1,pre[i]+1,i,v[i]);
for(;q[j].r==i;j++) ans[q[j].org]=query(1,n,1,q[j].l,i);
}
for(i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}
【BZOJ2482】[Spoj1557] Can you answer these queries II 线段树的更多相关文章
- BZOJ2482: [Spoj1557] Can you answer these queries II
题解: 从没见过这么XXX的线段树啊... T_T 我们考虑离线做,按1-n一个一个插入,并且维护区间[ j,i](i为当前插入的数)j<i的最优值. 但这个最优值!!! 我们要保存历史的最优值 ...
- bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树
2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 145 ...
- SPOJ 1557. Can you answer these queries II 线段树
Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/pr ...
- SPOJ GSS2 Can you answer these queries II ——线段树
[题目分析] 线段树,好强! 首先从左往右依次扫描,线段树维护一下f[].f[i]表示从i到当前位置的和的值. 然后询问按照右端点排序,扫到一个位置,就相当于查询区间历史最值. 关于历史最值问题: 标 ...
- Spoj 1557 Can you answer these queries II 线段树 随意区间最大子段和 不反复数字
题目链接:点击打开链接 每一个点都是最大值,把一整个序列和都压缩在一个点里. 1.普通的区间求和就是维护2个值,区间和Sum和延迟标志Lazy 2.Old 是该区间里出现过最大的Sum, Oldlaz ...
- SPOJ GSS1_Can you answer these queries I(线段树区间合并)
SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...
- SPOJ GSS3 Can you answer these queries III[线段树]
SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...
- GSS4 2713. Can you answer these queries IV 线段树
GSS7 Can you answer these queries IV 题目:给出一个数列,原数列和值不超过1e18,有两种操作: 0 x y:修改区间[x,y]所有数开方后向下调整至最近的整数 1 ...
- GSS5 spoj 2916. Can you answer these queries V 线段树
gss5 Can you answer these queries V 给出数列a1...an,询问时给出: Query(x1,y1,x2,y2) = Max { A[i]+A[i+1]+...+A[ ...
随机推荐
- 如何设定linux系统时间
1.设定日期 #date -s 09/28/2017 2.设定时间 #date -s 11:48:00 设定完了使用date命令查看系统时间,发现已经修改 下图是在Centos6.5 64位版上实际操 ...
- UVALive 3971 Assemble(模拟 + 二分)
UVALive 3971 题意:有b块钱.想要组装一台电脑,给出n个配件的种类,名字,价格,品质因子.若各种类配件各买一个,总价格<=b,求最差品质配件的最大品质因子. 思路: 求最大的最小值一 ...
- es6模块学习总结
模块功能主要由两个命令构成:export和import. export用于输出对外接口,improt用于输人接口 exprot 可以输出变量,也可以输出函数.类. 输出变量的三种写法 // 写法一ex ...
- SQLCMD Mode: give it one more chance
From : http://sqlblog.com/blogs/maria_zakourdaev/archive/2012/05/11/sqlcmd-mode-give-it-one-more-cha ...
- jsp+servlet实现文件下载
下载 1. 下载就是向客户端响应字节数据! 原来我们响应的都是html的字符数据! 把一个文件变成字节数组,使用response.getOutputStream()来各应给浏览器!!! 2. 下载的要 ...
- Visual studio C++ MFC之Menu editor
背景 本篇旨在MSDN帮助文档下总结Menu editor的使用,并列出碰到的具体问题. 正文 创建Menu Editor 打开链接MSDN之Creating a Menu.按照文档的方法创建Menu ...
- C语言-Makefile经典教程(掌握这些足够)
makefile很重要 什么是makefile? 或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional 的 ...
- C语言学习笔记(五) 数组
数组 数组的出现就是为了解决大量同类型数据的存储和使用的问题: 数组的分类:一维数组.二维数组. 一维数组:为多个变量连续分配存储控件:所有的变量的数据类型必须相同:所有变量所占的字节大小必须相等: ...
- SpringCloud系列六:Eureka的自我保护模式、IP选择、健康检查
1. 回顾 前面讲了很多Eureka的用法,比如Eureka Server.Eureka Server的高可用.Eureka Server的用户认证(虽然未完全实现).元数据等, 这章将讲解剩下的自我 ...
- Unity3d 引擎原理详细介绍、Unity3D引擎架构设计 - zhibolife
时间 2014-03-24 11:18:00 博客园-所有随笔区原文 http://www.cnblogs.com/zhibolife/p/3620440.html 体系结构 为了更好地理解游戏的 ...