[题解]CF1175E Minimal Segment Cover

思路

这是一道简单的 DP 题,DP 题的核心就是状态转移。

先来说一说 dp 数组的含义。

dpi,j 表示从 i 这个点用 2j 条线段能走到的最远的点。

我们再来考虑一下边界情况。

因为我们只用 20 条线段,那么:dpi,0=max(dpi,0,r)

接着,我们递推一遍,从前往后更新一遍最大值。

即:dpi,0=max(dpi,0,dpi1,0)

然后我们对 dp 数组进行递增。

即:dpj,i=dpdpj,i1,i1

注:以上递推和递增的操作都需要从 1N,原因是:我们操作都是预处理,最后直接求答案的。

最后,我们直接用一个循环来求出答案。

如果 dpx,i<y,那么我们的结果直接加上 2i,将 x 更新为 dpx,i

结果要加上 2i 的原因是:我们从 dp 数组的含义出发,我们需要的线段数量便是 2i

x 更新成 dpx,i 的原因是:我们把点 x 之前的所有点都走过了,所以我们直接更新即可

我们最后算出来的结果是终点的上一个点,所以我们需要判断一下最后一个是否有解就行了,如果有解输出结果 + 1,否则输出 -1

Code

#include <bits/stdc++.h>  
  
using namespace std;  
  
const int N = 5e5 + 10;  
int n,m;  
int dp[N + 100000/*要开大一点,不然越界*/][25];  
  
int main(){  
    cin >> n >> m;  
    for (int i = 1;i <= n;i++){  
        int a,b;  
        cin >> a >> b;  
        dp[a][0] = max(dp[a][0],b);  
    }  
    for (int i = 1;i <= N;i++) dp[i][0] = max(dp[i][0],dp[i - 1][0]);  
    for (int i = 1;i <= 19;i++){  
        for (int j = 0;j <= N;j++){  
            dp[j][i] = dp[dp[j][i - 1]][i - 1];  
        }  
    }  
    while (m--){  
        int x,y;  
        int res = 0;  
        cin >> x >> y;  
        for (int i = 19;i >= 0;i--){  
            if (dp[x][i] < y){  
                res += (1 << i);  
                x = dp[x][i];  
            }  
        }  
        if (dp[x][0] >= y) cout << res + 1 << endl;  
        else puts("-1");  
    }  
    return 0;  
}  

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18264792

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示