ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2390 地标访问

2022-08-07 13:33:21  阅读:99  来源: 互联网

标签:二分 P2390 路标 mid 访问 int 地标 端点


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~
} 

 

标签:二分,P2390,路标,mid,访问,int,地标,端点
来源: https://www.cnblogs.com/2elaina/p/16558917.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有