Can you answer these queries II
题意:
给一长度为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的更多相关文章
- BZOJ2482: [Spoj1557] Can you answer these queries II
题解: 从没见过这么XXX的线段树啊... T_T 我们考虑离线做,按1-n一个一个插入,并且维护区间[ j,i](i为当前插入的数)j<i的最优值. 但这个最优值!!! 我们要保存历史的最优值 ...
- 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 ...
- 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 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 ...
- 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 ...
- 【BZOJ2482】[Spoj1557] Can you answer these queries II 线段树
[BZOJ2482][Spoj1557] Can you answer these queries II Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和( ...
- SPOJ GSS2 Can you answer these queries II
Time Limit: 1000MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Description Being a ...
- GSS2-Can you answer these queries II
---恢复内容开始--- 这道题真的是非常恶心,看题解看了半天才弄懂,而且题解上说的相当简略. 此题大意是询问去掉重复元素的最大子区间和,没有修改操作. 没有修改操作,这样就可以离线处理了. 这道题有 ...
- SPOJ1557 GSS2 Can you answer these queries II 历史最值线段树
传送门 题意:给出一个长度为$N$的数列,$Q$次询问,每一次询问$[l,r]$之间的最大子段和,相同的数只计算一次.所有数字的绝对值$\leq 10^5$ GSS系列中不板子的大火题,单独拿出来写 ...
- 【SPOJ - GSS2】Can you answer these queries II(线段树)
区间连续不重复子段最大值,要维护历史的最大值和当前的最大值,打两个lazy,离线 #include<cstdio> #include<cstring> #include< ...
随机推荐
- Ubuntu下编译Poco库
本文主要记录下Ubuntu下编译Poco C++库的配置项以备后用.系统版本:Ubuntu 16.04,1 Poco 版本:1.9.0基本的步骤如下: 1.从官网下载最新的Poco源码,地址是:htt ...
- 工作总结 mvc外键 public virtual SysUser TransferUser { get; set; } 必须要加 virtual 否则 TransferUser 值为null 还要加[ForeignKey("TransferUser")] Bind 和 ScaffoldColumn(转)
[Table("T_SYS_TRANSFERUSER")] public class SysTransferUser : DbSetBase { [ForeignKey(" ...
- hessian实战1
服务端: 1.新建MAVEN HessianServer 项目 2.新建接口 Basic public interface Basic { String hello(String name); Str ...
- Mac OS command line TestNG - “Cannot find class in classpath” error
直接eclipse执行.xml文件可以正确执行 在mac下执行却总报错: [TestNG] [Error] Cannot find class in classpath 最后解决办法,classpat ...
- hive编程入门课程(加精)
hive编程入门课程 http://wenku.baidu.com/link?url=BfyZWjz48G_6UJImzWw39OLB0sUrIYEYxoxNpaFbADUQekmOvQy4FPY1f ...
- 20181125 test
1.对一些不确定性的东西,还是需要一些勇气进行尝试 2.多阅读blog上的大咖的文章肯定会有提高的
- Recurrent neural networks are very powerful, because they combine two properties
https://www.cs.toronto.edu/~hinton/csc2535/notes/lec10new.pdf Distributed hidden state that allows t ...
- ABAP抓取异常 try ,endtry.
DATA: O_CX TYPE REF TO CX_ROOT. TRY . MOVE LS_UPLOAD-MENGE TO LS_OUTPUT-MENGE. CATCH CX_ROOT INTO O_ ...
- UVA12293 Box Game —— SG博弈
题目链接:https://vjudge.net/problem/UVA-12293 题意: 两人玩游戏,有两个盒子,开始时第一个盒子装了n个球, 第二个盒子装了一个球.每次操作都将刷量少的盒子的球倒掉 ...
- HDU2222 Keywords Search —— AC自动机
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 Keywords Search Time Limit: 2000/1000 MS (Java/O ...