P2390 地标访问

https://www.luogu.com.cn/problem/P2390
搜索,贪心,二分
黄色题
 
思路:

其实我觉得吧,这题不用像大家说的,枚举左点,二分右点

题目问的是最多可以访问多少地标。稍稍分析可知,多访问一个路标,时间必定不会减少,显然这具有单调性质。于是很自然的可以想到去二分路标的个数呀QwQQwQ

先将所有路标的位置排序。要尽量使用时最少,那么我访问的任意两个路标之间都不能有其他的东西。(因为如果我访问的两个路标之间还有路标,那我还不如把这个路标顺便一起访问了呢)

那么,在存储路标位置的数组中,只要排好序,我访问的路标就一定是下标相邻的。

二分能访问到的路标个数,枚举右端点(当然左端点也行),判断这个区间是否能在tt的时间内访问完成。

最后右端点枚举完了,如果还没有找到解,那就证明当前二分的这个路标个数不行。

一直二分就行了。


复制代码
#include<bits/stdc++.h> using namespace std; int t,n; int a[100001]; bool check(int x){//判断函数,表示的是能否访问到x个路标 for(int r=x;r<=n;r++){//枚举右端点 int l=r-x+1; if(a[r]<=0)//如果右端点在原点左边,就要一直向左走 if(-a[l]<=t)return 1;//根据题意判断即可,可以就直接返回true if(a[l]>=0)//如果左端点在原点右边,就要一直向右走 if(a[r]<=t)return 1;//同上 if(a[l]<=0&&a[r]>=0)//如果这段区间横跨了原点 if(min(a[r],-a[l])+a[r]-a[l]<=t)return 1;//那么我一定是先去距离原点短的那一边,再走到另一边 } return 0;//如果整个循环执行完,没有找到可行解,那就返回false } int main(){ cin>>t>>n; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+1+n);//给所有路标位置排序 int l=-1,r=n+1;//由于能访问的路标数量可能为0~n,所以把左边界设为1,右边界设为n+1,就可以保证二分到所有解 while(l+1<r){//这里写l+1<r是为了防止最后l,r出现交叉的情况,即l>r int mid=(l+r)>>1; if(check(mid))l=mid; else r=mid; //更新l,r的值时写mid而不是mid+1或mid-1,也是为了防止最后l>r } cout<<l<<endl;最后输出l return 0;//Happy ending~ }
复制代码

 


__EOF__

本文作者灰の魔女伊蕾娜
本文链接https://www.cnblogs.com/2elaina/p/16558917.html
关于博主:编程小萌新一名,希望从今天开始慢慢提高,一步步走向技术的高峰!
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   -イレイナ  阅读(70)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示