题意:

给一长度为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. LVDS、MIPI、EDP、VGA、DVI、HDMI、DP3.0(雷电接口)

    1.LVDS 2.mipi 3.EDP:Embedded DisplayPort 4.VGA VGA接口的特性: 1)理论上能够支持2048x1536分辨率画面传输. 2)VGA由于是模拟信号传输,所 ...

  2. Swift的两个小窍门

    一:查看Swift版本号(How do I see which version of Swift I’m using in Xcode?) 终端下输入:xcrun swift -version(in ...

  3. 从头认识java-14.1 再次对照数组与容器

    这一章节我们再次深入的对照数组与容器. 数组与容器主要集中在三个方面:效率.类型.基础类型. 我们能够从三方面做出对照. 1.效率 这里的下来是指add和get 的速度 以下以add为例: packa ...

  4. JS 模板引擎 Handlebars.js 中文说明

    Handlebars 为你提供了一个可以毫无挫折感的高效率书写 语义化的模板 所必需的一切. Mustache 模板和 Handlebars 是兼容的,所以你可以把Mustache模板拿来导入到Han ...

  5. 【TensorFlow-windows】(五) CNN(卷积神经网络)对cifar10的识别

    主要内容: 1.基于CNN的cifar10识别(详细代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3-4.2.0-Windows-x86_64.ex ...

  6. session自己定义存储,怎样更好地进行session共享;读tomcat7源代码,org.apache.catalina.session.FileStore可知

    session自己定义存储.怎样更好地进行session共享: 读tomcat源代码,org.apache.catalina.session.FileStore可知 一.详见: 方法1 public ...

  7. requests 中文乱码

    jsUrl = 'http://www.heze.cn/qiye/index.php?a=userinfo&username={}'.format(bizQiyeId)r = requests ...

  8. it starts (“forks”) a new process for each connection.

    PostgreSQL: Documentation: 10: 1.2. Architectural Fundamentals https://www.postgresql.org/docs/10/st ...

  9. python自动化运维九:Playbook

    playbook:playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,pla ...

  10. ABAP- INCLUDE Zxxx IF FOUND.

    大顾代码: INCLUDE zinc_ca_0002 IF FOUND. - 这肯定是大顾问写出来的 - 一般都不会加东西啊 -加了 IF FOUND 不知道啥意思.  古道无仙(173120830) ...