题意:

给一长度为n的序列,有m组询问,每一组询问给出[l,r]询问区间内的最大去重连续子段和。

解法:

考虑一下简化后的问题:如果题目要求询问查询以$r$为右端点且$l$大于等于给定值的去重连续子段和,

那么我们显然可以预处理出$pre(i)$表示$i$位置出现的数字上一次出现的位置。

那么我们可以从小到大枚举$r$,

线段树维护$[i,r]$的去重子段和,区间加+维护最大值进而求出$[i,r]$的去重子段和的最大值。

现在考虑r小于等于给定值的做法,

注意到r是从1开始到n枚举的,进而保证了线段树里出现过的值都是$[l_i,r_i],r_i<=r$的去重子段和。

所以我们只要维护一下历史上线段树$i$位置出现过的历史最大值即可。

注意区间加的$add$标记不可以简单的合并,

因为我们要求的是历史上出现过的最大值,有可能$add 2, add -2$两个标记合并为$add 0$,进而错过最优答案。

对于一个点的$add$操作可以认为是一个$add$的序列,

我们要维护$add$序列中出现过的最大的前缀和,类比经典的处理方法最大子段和。

注意到线段树要维护4个标记:

历史最大值

当前最大值

当前$add$

$add$序列里的最大前缀和

总效率$O(nlogn)$

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm> #define N 100010
#define l(x) ch[x][0]
#define r(x) ch[x][1]
#define LL long long
#define INF 0x3f3f3f3f using namespace std; struct node
{
int l,r,id;
}b[N]; int n,totn,m;
int a[N],pre[N],a0[N];
int ch[N<<][];
LL max_all[N<<],maxv[N<<];
LL add_all[N<<],addv[N<<];
LL ansv[N];
map<int,int> pos; bool cmp(node a,node b)
{
return a.r<b.r;
} void push(int x)
{
if(!addv[x] && !add_all[x]) return;
add_all[l(x)]=max(add_all[l(x)],addv[l(x)]+max(add_all[x],0LL));
max_all[l(x)]=max(max_all[l(x)],maxv[l(x)]-addv[l(x)]+max(add_all[l(x)],0LL));
addv[l(x)]+=addv[x];
maxv[l(x)]+=addv[x]; add_all[r(x)]=max(add_all[r(x)],addv[r(x)]+max(add_all[x],0LL));
max_all[r(x)]=max(max_all[r(x)],maxv[r(x)]-addv[r(x)]+max(add_all[r(x)],0LL));
addv[r(x)]+=addv[x];
maxv[r(x)]+=addv[x];
addv[x]=;
add_all[x]=;
} void update(int x)
{
maxv[x]=max(maxv[l(x)], maxv[r(x)]);
max_all[x]=max(max_all[x],max_all[l(x)]);
max_all[x]=max(max_all[x],max_all[r(x)]);
} LL ask(int x,int l,int r,int ql,int qr)
{
push(x);
if(ql<=l && r<=qr) return max_all[x];
int mid=(l+r)>>;
LL ans=;
if(ql<=mid) ans = max(ans, ask(l(x),l,mid,ql,qr));
if(mid<qr) ans = max(ans, ask(r(x),mid+,r,ql,qr));
update(x);
return ans;
} void add(int x,int l,int r,int ql,int qr,LL qv)
{
push(x);
if(ql<=l && r<=qr)
{
addv[x]=qv;
add_all[x]=max(qv,0LL);
maxv[x]+=qv;
max_all[x]=max(max_all[x],maxv[x]);
return;
}
int mid=(l+r)>>;
if(ql<=mid) add(l(x),l,mid,ql,qr,qv);
if(mid<qr) add(r(x),mid+,r,ql,qr,qv);
update(x);
} int build(int l,int r)
{
int x=++totn;
max_all[x]=maxv[x]=;
add_all[x]=;
addv[x]=;
if(l==r) return x;
int mid=(l+r)>>;
l(x)=build(l,mid);
r(x)=build(mid+,r);
return x;
} int main()
{
while(~scanf("%d",&n))
{
for(int i=;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&b[i].l,&b[i].r);
b[i].id=i;
}
sort(b+,b+m+,cmp);
totn=;
pos.clear();
for(int i=;i<=n;i++)
{
if(pos.count(a[i])) pre[i]=pos[a[i]];
else pre[i]=,a0[i]=a[i];
pos[a[i]]=i;
}
build(,n);
int j=;
for(int i=;i<=n;i++)
{
add(,,n,pre[i]+,i,a[i]);
while(j<=m && b[j].r==i)
{
ansv[b[j].id]=ask(,,n,b[j].l,b[j].r);
j++;
}
}
for(int i=;i<=m;i++)
printf("%lld\n",ansv[i]);
}
return ;
}

Can you answer these queries II的更多相关文章

  1. BZOJ2482: [Spoj1557] Can you answer these queries II

    题解: 从没见过这么XXX的线段树啊... T_T 我们考虑离线做,按1-n一个一个插入,并且维护区间[ j,i](i为当前插入的数)j<i的最优值. 但这个最优值!!! 我们要保存历史的最优值 ...

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

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

  4. spoj gss2 : Can you answer these queries II 离线&&线段树

    1557. Can you answer these queries II Problem code: GSS2 Being a completist and a simplist, kid Yang ...

  5. SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)

    GSS2 - Can you answer these queries II #tree Being a completist and a simplist, kid Yang Zhe cannot ...

  6. 【BZOJ2482】[Spoj1557] Can you answer these queries II 线段树

    [BZOJ2482][Spoj1557] Can you answer these queries II Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和( ...

  7. SPOJ GSS2 Can you answer these queries II

    Time Limit: 1000MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description Being a ...

  8. GSS2-Can you answer these queries II

    ---恢复内容开始--- 这道题真的是非常恶心,看题解看了半天才弄懂,而且题解上说的相当简略. 此题大意是询问去掉重复元素的最大子区间和,没有修改操作. 没有修改操作,这样就可以离线处理了. 这道题有 ...

  9. SPOJ1557 GSS2 Can you answer these queries II 历史最值线段树

    传送门 题意:给出一个长度为$N$的数列,$Q$次询问,每一次询问$[l,r]$之间的最大子段和,相同的数只计算一次.所有数字的绝对值$\leq 10^5$ GSS系列中不板子的大火题,单独拿出来写 ...

  10. 【SPOJ - GSS2】Can you answer these queries II(线段树)

    区间连续不重复子段最大值,要维护历史的最大值和当前的最大值,打两个lazy,离线 #include<cstdio> #include<cstring> #include< ...

随机推荐

  1. pycharm5.0 激活方式

    Pycharm5注册方式   0x1 ,安装 0x2 , 调整时间到2038年. 0x3 ,申请30天试用 0x4, 退出pycharm 0x5, 时间调整回来. ##注册方法2### 注册方法:   ...

  2. 3D打印技术之切片引擎(4)

    [此系列文章基于熔融沉积( fused depostion modeling, FDM )成形工艺] 这一篇文章我讲一下多边打印的问题,多边打印是切片引擎的一项关键的技术. 图1 双边打印 首先.它能 ...

  3. caffe搭建--WINDOWS+VS2013下生成caffe并进行cifar10分类测试

    http://blog.csdn.net/naaaa/article/details/52118437 标签: windowsvs2013caffecifar10 2016-08-04 15:33 1 ...

  4. 基于struts2的学生报道管理系统(附github源码地址)

    本项目参考了<java web轻量级开发全体验>,加入了对mysql的支持. 一.基本业务功能 通过struts2框架,结合mysql数据库构建一个学生报到管理系统,来模拟学生报到登记的过 ...

  5. 在yum出问题的情况下安装某个rpm包的方法

    1 核心命令 rpm -i 2 方法 centos镜像站去找到所有的rpm包. 安装这个rpm包,发现有一个依赖没有安装,就去下载安装.因为整体的包是有限的,因此终会收敛的. 比如安装rpmbuild ...

  6. llmp_install.zip

    https://pan.baidu.com/s/14tQdE9CPe55P5m9rGm5ekw

  7. [IR课程笔记]概率检索模型

    几个符号意义: R:相关文档集 NR:不相关文档集 q:用户查询 dj:文档j 1/0风险情况 PRP(probability ranking principle):概率排序原理,利用概率模型来估计每 ...

  8. querySelectorAll和getElementsBy 系列比较

    querySelectorAll 相比下面这些方法有什么区别? (1)getElementsByTagName (2)getElementsByClassName (3)getElementsByNa ...

  9. javase练习题--每天写写

    package com.javaTestDemo; import java.util.Scanner; public class JavaTest1 { public static void main ...

  10. 基于BASYS2的VHDL程序——数字钟

    在编电子表时发现FPGA求余,取模只能针对2的次方.毕竟是数字的嘛! 时钟用到了动态刷新数码管.以一个大于50Hz的速度刷新每一个数码管. 因为数码管只有四个,只写了分针和秒针. 代码如下: libr ...