时光倒流+暴力+尺取


第一次看到这题,是在神子杏的课堂上

这就是一个裸的双指针,洛咕上多倍经验的题太多了。 ——神子杏

那好,我们就用双指针来考虑这道题。

首先可以发现

  • 答案区间$ (l,r) $ 一定在某两个标记点之间,也就是说,$l-1 $ 应当是一个有标记点,\(r+1\) 也应是一个有标记的点。

证明很显然,假如右端点的右侧没有标记,那么右端点一定可以继续向右延伸。左端点同理。

往数轴上增加标记不好做,考虑从数轴上拿走标记。我们可以预处理出所有标记点都在数轴上时的答案,也就是输出答案的最后一行。关于这一步,我们可以发现暴力枚举每一个可能的答案区间\((l,r)\)的复杂度为\(O(n^2)\),这显然是不能接受的。发现每当我们确定一个左端点l,则随着l的增大,r是单调不降的。基于这一性质,考虑用双指针扫一遍,\(O(n)\)美滋滋。

接下来考虑依次删去每一个标记,即将这一标记的权值设为\(0\),同时统计对应的答案。统计答案的方法同上。但是我们会发现这样单次复杂度最坏是\(O(n)\),不能接受。

还需要注意的是,题目中要求标记个数不大于k,发现k很小,考虑暴力做。可以发现

  • 删除一个标记点时,至多只会影响这个点左侧k个和右侧k个点(想一想,为什么)。

所以我们只需要在每次删除时,以\(O(k)\)的复杂度用双指针来找这个标记点的左右能不能作为答案即可。

继续考虑优化。删除一个标记,我们不仅删除它的权值,而且删除这个标记的在数组存储中的下标,枚举端点的时候直接跳过它。没错,我们可以使用一个链表来维护每一个端点的前驱和后继。在删除标记时,只需修改其前驱后继的关系即可。

最后需要特判一种情况:删除上一个标记点时的答案区间为\((l0,r0)\),删除当前标记点的答案区间为\((l,r)\),两个区间不是包含关系。这时需要将当前的答案取两者中较大的即可。

则总复杂度为\(O(nk)\)

Code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e+6+100;
const int inf = 0x7f7f7f7f;
struct Data{
int x,a,tim;
};
int n,m,k;
Data opt[maxn];
int tim[maxn];
int ans[maxn];
int pre[maxn],suc[maxn];
inline int read(){
int v=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-f; ch = getchar();}
while(ch>='0'&&ch<='9'){v=(v<<3)+(v<<1)+ch-'0';ch=getchar();}
return v*f;
}
inline bool cmp(Data x,Data y){
return x.x<y.x;
}
int main(){
n=read();m=read();k=read();
for(register int i=1;i<=n;++i){
opt[i].x=read();opt[i].a=read();opt[i].tim = i;
ans[i] = -1;
}
opt[n+1]=Data{-1,inf,0};
opt[n+2]=Data{m+1,inf,0};
sort(opt+1,opt+n+3,cmp);
for(register int i=1;i<=n+2;++i) tim[opt[i].tim] = i;
for(register int l=1,r=1,cnt=0;r<=n+2;++r){
cnt+=opt[r].a;
while(cnt>k){
cnt-=opt[l++].a;
if(l>r) break;;
}
if(k==0) ans[n] = max(ans[n],opt[r].x-opt[r-1].x-2);
else ans[n]=max(ans[n],opt[r+1].x-opt[l-1].x-2);
}
for(register int i=1;i<=n+2;++i){
if(i!=1)pre[i] = i-1;
suc[i] = i+1;
}
for(register int i=n-1;i>=1;--i){
int t=tim[i+1];
opt[t].a=0;
pre[suc[t]] = pre[t];
suc[pre[t]] = suc[t];
int r=t,lim=t;
for(int p=0;p<=k+10;++p){
r=max(pre[r],2);
lim=min(suc[lim],n+2);
}
for(register int l=r,cnt=0;r<=lim;r=suc[r]){
cnt+=opt[r].a;
while(cnt>k){
cnt-=opt[l].a;
l=suc[l];
}
if(k==0) ans[i] = max(ans[i],opt[r].x-opt[pre[r]].x-2);
else ans[i] = max(ans[i],opt[suc[r]].x-opt[pre[l]].x-2);
}
ans[i]=max(ans[i+1],ans[i]);
}
for(register int i=1;i<=n;++i) printf("%d\n",ans[i]);
return 0;
}

洛谷 P6602 数轴的更多相关文章

  1. USACO Section 1.3 题解 (洛谷OJ P1209 P1444 P3650 P2693)

    usaco ch1.4 sort(d , d + c, [](int a, int b) -> bool { return a > b; }); 生成与过滤 generator&& ...

  2. 洛谷AT2046 Namori(思维,基环树,树形DP)

    洛谷题目传送门 神仙思维题还是要写点东西才好. 树 每次操作把相邻且同色的点反色,直接这样思考会发现状态有很强的后效性,没办法考虑转移. 因为树是二分图,所以我们转化模型:在树的奇数层的所有点上都有一 ...

  3. [洛谷P4609] [FJOI2016]建筑师

    洛谷题目链接:[FJOI2016]建筑师 题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 \(n\) 个建筑,每个建筑的高度是 \(1\) 到 \(n\) 之间的一 ...

  4. 【洛谷】P1052 过河【DP+路径压缩】

    P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...

  5. 「洛谷5017」「NOIP2018」摆渡车【DP,经典好题】

    前言 在考场被这个题搞自闭了,那个时候自己是真的太菜了.qwq 现在水平稍微高了一点,就过来切一下这一道\(DP\)经典好题. 附加一个题目链接:[洛谷] 正文 虽然题目非常的简短,但是解法有很多. ...

  6. 洛谷疯狂coding~

    1.关于数学建模思想在coding之中的应用. 将马路作为一条数轴,每棵树的位置作为数轴上的坐标点,再将坐标点与数组的下标联系到一起,完成建模. 2.本题坑点在于对“其中有多少个数,恰好等于集合中另外 ...

  7. 洛谷P1052 过河

    P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上. 由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青 ...

  8. 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化

    洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

随机推荐

  1. Gradle系列之Android Gradle插件

    原文发于微信公众号 jzman-blog,欢迎关注交流. 通过前面几篇文章学习了 Gradle 基础知识以及 Gradle 插件相关的知识,关于 Gradle 及其插件相关知识请先阅读下面几篇文章: ...

  2. 移动web开发之rem适配布局

    移动web开发之rem适配布局 方案: 页面布局文字能否随着屏幕大小变化而变化 流式布局和flex布局主要针对于宽度布局,那高度如何布局? 怎样让屏幕发生变化的时候元素高度和宽度等比例缩放? 1. r ...

  3. Express下ejs的视图模板引擎的建立

    写在前面 由于Express升级到4.0,将ejs的用法忽略,改为用户自定义形式,所以要引入库index.js作为引擎,来支持ejs的模板引擎(点击下载). 首先是建立一个名字叫nodeitem,引擎 ...

  4. J.U.C之Executor框架入门指引

    1.Executor接口 This interface provides a way of decoupling task submission from the mechanics of how e ...

  5. windows服务器中创建账号及管理相关的net命令

    本文测试环境:windows server 2012 R2 Datacenter 实例要求: 1.创建账号,加入到远程桌面组,能实现远程桌面登录 2.指定Full name .及Description ...

  6. spring aop原理和实现

    一.aop是什么 1.AOP面向方面编程基于IoC,是对OOP的有益补充: 2.AOP利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了 多个类的公共行为封装到一个可 ...

  7. Java基础一篇过(八)常见异常速查

    一.引言 开发过程中可能会遇到各种各样的异常,这里还是汇总一些比较典型的异常,有些比较直观的异常如空指针这种就不写了,此文可作为异常速查用. 二.异常大军正在来袭~ IllegalArgumentEx ...

  8. Spring属性注入(set方式、构造函数方式、p名称空间、spel、复杂类型)

    1.set注入方式 (1)注入的为值类型(八大数据类型)的数据 配置文件: <?xml version="1.0" encoding="UTF-8"?&g ...

  9. 永久改变cmd背景颜色

    问题描述:cmd窗口为白底黑字,用久之后想换背景颜色. 解决方法一: win+R 输入regedis进入注册表,找到 HKEY_CURRENT_USER\Software\Microsoft\Comm ...

  10. python3-day3

    一.函数基本语法及特性 重复用到的代码通过def封装起来,用到的时候直接调用函数名字:语法 1 def 函数名字(内容): 2 需要执行的动作 什么是函数: 函数一词来源于数学,但编程中的「函数」概念 ...