蓝桥杯2023年-管道(二分+区间合并)

文章讲述了如何解决一个关于水管管道的问题,给定阀门开放时间和位置,计算使所有管道段传感器检测到水流的最小时间。利用二分查找和区间合并算法优化求解过程。
摘要由CSDN通过智能技术生成

题目描述

有一根长度为 len 的横向的管道,该管道按照单位长度分为 len 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。 

一开始管道是空的,位于 Li 的阀门会在 Si 时刻打开,并不断让水流入管道。

对于位于 Li 的阀门,它流入的水在 Ti (Ti ≥ Si) 时刻会使得从第 Li−(Ti−Si) 段到第 Li + (Ti − Si) 段的传感器检测到水流。 求管道中每一段中间的传感器都检测到有水流的最早时间。

思路

(一开始没有弄懂题目意思,以为是覆盖所有给定的阀门就行,结果浪费不少时间,,一定先要读懂题啊啊啊)

题目意思大概是:给定一个1~len的区间,区间里面有n个水闸分别会在ti时刻放水,求水将整个区间全部覆盖所需的最少时间。

明显这个时间是线性的,即时间越长,覆盖的范围越大。所以我们可以二分这个时间。

在时间t下,枚举出每个水闸覆盖的区间,得到若干个区间。然后对这些区间先进行初步排序,然后进行区间合并。如果合并后的区间覆盖了完整的1~len的区间,则check返回true。

注意点:

1、记得先要对区间进行排序,再进行区间合并

2、二分的边界是1~2e9+1,因为最差的情况是1e9时开始放水,然后再要跑1e9个格子,所以总共需要2e9+1的时间。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
    int pos;
    int t;
};
struct edg{
    int l;
    int r;
};
bool cmp(node a,node b){
    return a.pos<b.pos;
}
bool cmp1(edg a,edg b){
    if(a.l!=b.l)
    return a.l<b.l;
    return a.r<b.r;
}
vector<node>q;
int n,m;
bool check(int k){
    vector<edg>e;
    for(int i=0;i<n;i++){
        if(k<q[i].t)continue;
        int sub=k-q[i].t;
        int l=q[i].pos-sub;
        int r=q[i].pos+sub;
        e.push_back({l,r});
    }
    if(e.size()==0)return 0;
    sort(e.begin(),e.end(),cmp1);
    if(e[0].l>1)return 0;
    int i=0;
    int r=e[i].r;
    i++;
    while(i<e.size()&&r>=e[i].l-1){
        r=max(r,e[i].r);
        i++;
    }
    return r>=m;
}
signed main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        int a,b;cin>>a>>b;
        q.push_back({a,b});
    }
    int l=1,r=2e9+10;
    while(l<r){
        int mid=r+l>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    cout<<l;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值