CodeForces - 1175E Minimal Segment Cover

本文介绍了一个使用倍增算法解决区间覆盖问题的算法题解。通过预处理每个区间的最远可达右端点,并利用动态规划进行状态转移,实现了高效的查询处理。适用于多次询问场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://codeforces.com/problemset/problem/1175/E

题目大意:给n个区间,询问m次,每次给出能覆盖【x,y】最少的区间数。

假如询问一次,可以考虑用贪心做,但是此题询问m次,可以用倍增的方法计算出来。

思路:

r【i】:表示从i开始能覆盖的最大的右端点值。

更新r[i]:(1)因为可能有多个区间从i开始,取右端点最大的1个。 时预处理,  r[x]=max(r[x],y);

                 (2)   i的左边i-1也可以更新r[i].r[i]=max(r[i-1],r[i]).

dp[j][i]:表示从i开始, 2^j个区间能到达的最大的右端点。

状态转移:dp[j][i]=dp[j-1][dp[j-1][i]]. (类似基本的倍增,将2^j个区间分为两个2^(j-1)区间求)。

#include <iostream>
#define MA 500005
using namespace std;

int dp[20][MA],n,m,x,y,r[MA];
int main()
{
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        cin>>x>>y;
        r[x]=max(r[x],y);
    }
    dp[0][0]=r[0];
    for(int i=1; i<MA; i++){
        r[i]=max(r[i-1],r[i]);
        dp[0][i]=r[i];
    }
    for(int j=1; j<20; j++){
       for(int i=0; i<MA; i++){
          dp[j][i]=dp[j-1][dp[j-1][i]];//关键
       }
    }
    while(m--){
       cin>>x>>y;
       int cnt=0;
       for(int i=19; i>=0;i--){
           if(dp[i][x]<y){//每次寻找一个最大幂次值,使得dp[i][x]严格小于y,超过y可能会浪费多余的区间
              x=dp[i][x];
              cnt+=(1<<i);
           }
       }
       if(dp[0][x]<y){//假如从x再走一步到不了y
          cout<<"-1"<<endl;
       }
       else{//再从x取1个区间就可以覆盖了。
          cout<<cnt+1<<endl;
       }
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值