【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[ ...
随机推荐
- Selenium webdriver Java 封装与重用
目的 1. 简化调用 WebDriver对页面的操作,需要找到一个WebElement,然后再对其进行操作,比较繁琐: WebElement element =driver.findElement(B ...
- vue - 认识ora
主要用来实现node.js命令行环境的loading效果,和显示各种状态的图标等... const ora = require('ora'); const spinner = ora('Loading ...
- sql中update,alter,modify,delete,drop的区别和使用(整理)
关于update和alter: 百度知道上关于update和alter有一个很形象的总结: 一个表有很多字段,一个字段里有很多数据. 一个家有很多房间,一个房间里有很多家具. update是用来将衣柜 ...
- Jmeter-性能测试(三)
一.调通脚本(以json串Post接口为例)添加聚合报告(线程组->添加->监听器->聚合报告)并调试好需要压测的脚本,如下已经调通的P_C_B151就是我需要压测的脚本 二.设置场 ...
- js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
代码如下: /** 音乐播放器 * @param obj 播放器id * @param file 音频文件 mp3: ogg: * @param loop 是否循环 */ function audio ...
- lucene 异常 Lock obtain timed out 解决方法
http://terje.blog.163.com/blog/static/119243712008102122316595/ 一般都是索引建立的过程中,不正常操作影响了IndexWriter ...
- docker发布spring cloud应用
原文地址:http://www.cnblogs.com/skyblog/p/5163691.html 本文涉及到的项目: cloud-simple-docker:一个简单的spring boot应用 ...
- vmware安装问题:Microsoft Runtime DLL安装程序未能完成安装
下载vmware station 12 pro后安装,发现有以下问题: 解决方法: 在提示这个页面的时候,在运行中输入: %temp% 在打开来的文件窗口中,找到末尾为 ~setup的文件夹, ...
- postman --发送json请求
转自: http://blog.csdn.net/wangjun5159/article/details/47781301 简介: postman是一个很好的http模拟器,在测试rest服务时是很好 ...
- 121. Best Time to Buy and Sell Stock【easy】
121. Best Time to Buy and Sell Stock[easy] Say you have an array for which the ith element is the pr ...