E. Minimal Segment Cover (贪心+倍增)

传送门

给定一个数轴,给定n条线段,每条线段可以覆盖[li,ri]的位置,q次询问,每次问如果要覆盖[l,r],最少要选多少条线段。

在这里插入图片描述

先考虑一个贪心的暴力解法:
对于询问[L,R],假设当前位置为l,我们要从左端点小于等于l的线段中找到一个最大的右端点r,并让当前位置更新为r,直到R==r

尽管我们可以预处理得到a[i]表示从i位置只选一个线段能到达右边最远的位置是哪里, 暴力解法时间复杂度仍为 O(nq).


既然i位置能够选一条线段最远到达a[i],同时a[i]位置能选一条线段最远到达a[a[i]],那么i位置可以选x条线段最远到达的地方也是可以求的,(相当于我们知道每个位置走一步到达的地方,那么就可以求出每个位置走k步到达的地方),但是遍历x次去求太慢了。

我们把x写成二进制,假设为1011,那么我们只要知道i走1000,10,1步到达的地方,就可以求出x步的答案了,这就是倍增的思想,通过二进制表示使得遍历[1,x]的时间复杂度降到logx .

关于倍增的讲解可以参考:大佬的文章

回到这个问题,我们通过倍增在nlogn的预处理时间内,求出了每个点选x条线段能够到达的最远地方,那么每次询问,我们就从l位置出发,求出这个最小的x。

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define ull unsigned long long
#define ll long long
#define pii pair<int, int>
const int maxn = 5e2 + 10;
const ll mod = 1e9 + 7;
const ll inf = (ll)4e16+5;
const int INF = 1e9 + 7
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值