洛谷 P6602 数轴
时光倒流+暴力+尺取
第一次看到这题,是在神子杏的课堂上
这就是一个裸的双指针,洛咕上多倍经验的题太多了。 ——神子杏
那好,我们就用双指针来考虑这道题。
首先可以发现
- 答案区间$ (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 数轴的更多相关文章
- 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&& ...
- 洛谷AT2046 Namori(思维,基环树,树形DP)
洛谷题目传送门 神仙思维题还是要写点东西才好. 树 每次操作把相邻且同色的点反色,直接这样思考会发现状态有很强的后效性,没办法考虑转移. 因为树是二分图,所以我们转化模型:在树的奇数层的所有点上都有一 ...
- [洛谷P4609] [FJOI2016]建筑师
洛谷题目链接:[FJOI2016]建筑师 题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 \(n\) 个建筑,每个建筑的高度是 \(1\) 到 \(n\) 之间的一 ...
- 【洛谷】P1052 过河【DP+路径压缩】
P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...
- 「洛谷5017」「NOIP2018」摆渡车【DP,经典好题】
前言 在考场被这个题搞自闭了,那个时候自己是真的太菜了.qwq 现在水平稍微高了一点,就过来切一下这一道\(DP\)经典好题. 附加一个题目链接:[洛谷] 正文 虽然题目非常的简短,但是解法有很多. ...
- 洛谷疯狂coding~
1.关于数学建模思想在coding之中的应用. 将马路作为一条数轴,每棵树的位置作为数轴上的坐标点,再将坐标点与数组的下标联系到一起,完成建模. 2.本题坑点在于对“其中有多少个数,恰好等于集合中另外 ...
- 洛谷P1052 过河
P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上. 由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青 ...
- 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化
洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
随机推荐
- JVM运行时数据区--堆
一个进程对应一个jvm实例,一个运行时数据区,又包含多个线程,这些线程共享了方法区和堆,每个线程包含了程序计数器.本地方法栈和虚拟机栈. 核心概述 1.一个jvm实例只存在一个堆内存,堆也是java内 ...
- Golang的Context介绍及其源码分析
简介 在Go服务中,对于每个请求,都会起一个协程去处理.在处理协程中,也会起很多协程去访问资源,比如数据库,比如RPC,这些协程还需要访问请求维度的一些信息比如说请求方的身份,授权信息等等.当一个请求 ...
- java Synchronized集合
在Collections存在相关"Synchronized"支持同步的集合, 在java1.0 也存在"Vector"; 为什么会选择放弃"Vecto ...
- spring-dao.xml通常写法
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- 我把公司 10 年老系统改造 Maven,真香!!
公司有几个老古董项目,应该是 10 年前开发的了,有一个是 JSP + Servlet,有一个还用的 SSH 框架,打包用的 Ant,是有多老啊,我想在座的各位很多都没听过吧. 为了持续集成.持续部署 ...
- NodeJS沙箱逃逸&&vm
NodeJS沙箱逃逸 关于nodejs的沙箱 使用场景 在线代码编辑器 第三方js代码 jsonp,like百度搜索框 https://www.baidu.com/s?wd=nodejs&mi ...
- springboot maven项目运行常见报错 及ajax请求报错
如图所示 tomcat运行后直接停止,也不报错 原因:我的原因是controller路径配置重名或者service没有配置@Service 遇见这错找了好久问题,网上也搜不到,特此记录一下 问题2 a ...
- SpringBoot+RabbitMQ 方式收发消息
本篇会和SpringBoot做整合,采用自动配置的方式进行开发,我们只需要声明RabbitMQ地址就可以了,关于各种创建连接关闭连接的事都由Spring帮我们了~ 交给Spring帮我们管理连接可以让 ...
- IPV6介绍已经IPV6改造基本步骤
IPV6介绍 地址资源无限多 通常见到的124.33.24.116这种形式的是ipv4版本的地址,这种地址由32位二进制数表示. ipv6是一种新的ip地址的表示方式形如fc80::2367:7cff ...
- Linux系统编程 —时序竞态
时序竞态 什么是时序竞态?将同一个程序执行两次,正常情况下,前后两次执行得到的结果应该是一样的.但由于系统资源竞争的原因,前后两次执行的结果有可能得到不一样的结果,这个现象就是时序竞态. pause函 ...