H2330819027


私信TA

用户名:dotcpp0701405

访问量:9829

签 名:

指向函数指针数组的指针int(*(*p[4]))(int int)

等  级
排  名 125
经  验 7649
参赛次数 1
文章发表 79
年  龄 18
在职情况 学生
学  校 Hzu university
专  业 软件工程

  自我简介:

首先根据题意,假如说在t时刻满足题目要求,那么比t大的时刻也一定满足要求,故具有单调性,此时可以想到用二分来做。

对于每个二分出来的时刻,可以将每一个水阀所能检测的范围算出来(若该时刻小于水阀打开的时刻,则该水阀跳过)。此时问题就变成了对于这些所检测出来的范围是否能覆盖整个管道,显然是一个区间合并知识点。将所有区间合并之后,再看看该区间是否能覆盖11~len的位置即可。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>

#define x first
#define y second

using namespace std;
using ll = long long;
typedef pair<int, int> PII;
const int N = 1e5 + 3;

int n, m; // n表示水阀数量,m表示管道长度
PII w[N], q[N]; // 定义长度为N的水阀数组w,和临时数组q

bool check(int mid)
{
    int cnt = 0; // 初始化计数器为0,用于统计每个水阀的有效区间
    for (int i = 1; i <= n; i++)
    {
        int L = w[i].x, S = w[i].y; // 获取当前水阀的位置L和打开时间S
        if (mid >= S) // 如果mid大于等于水阀打开时间S
        {
            int t = mid - S; // 计算时间差
            int l = max(1, L - t), r = min((ll)m, (ll)L + t); // 计算有效区间的左右边界
            q[cnt++] = {l, r}; // 将有效区间更新到临时数组q中
        }
    }
    sort(q, q + cnt); // 对有效区间进行排序

    int st = -1, ed = -1; // 初始化起点和终点
    for (int i = 0; i < cnt; i++) // 遍历有效的区间
    {
        if (q[i].x <= ed + 1) // 如果当前区间的左边界小于等于前一个区间的右边界+1
            ed = max(ed, q[i].y); // 更新终点
        else
            st = q[i].x, ed = q[i].y; // 否则更新起点和终点
    }
    return st == 1 && ed == m; // 返回有效区间是否覆盖了整个管道
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 加速输入输出
    cin >> n >> m; // 读取水阀数量和管道长度
    for (int i = 1; i <= n; i++) // 遍历水阀
        cin >> w[i].x >> w[i].y; // 读取每个水阀的位置和打开时间
    ll l = 0, r = 2e9; // 初始化左边界l为0,右边界r为2e9
    while (l < r) // 二分查找
    {
        ll mid = l + r >> 1; // 计算中点
        if (check(mid)) // 调用函数检查中点是否符合要求
            r = mid; // 更新右边界
        else
            l = mid + 1; // 更新左边界
    }
    cout << r; // 输出结果
    return 0; // 返回0,表示程序执行成功
}


 

0.0分

2 人评分

  评论区