要求至少用几个线段覆盖一个区间,多个询问。我们可以贪心。每次寻找当前已经覆盖到的位置l,找左端点在 0~l 能覆盖到的最右区间,其实对于每个位置0~l,我们只需记录最右的那个区间即可,然后可以倍增优化这个跳的过程
初始f[0][i]表示的是左端点小于i,右端点最远的地方,我们可以从从左往右来更新
这里提供了一个用并查集实现的离线算法https://www.cnblogs.com/chasedeath/p/12267839.html
const int N = 5e5 + 97;
int n, q;
int l, r;
int f[24][N];
int main() {
read(n);
read(q);
memset(f, 0xff, sizeof f);
rep(i, 1, n) {
read(l);
read(r);
f[0][l] = max(f[0][l], r);
}
rep(i, 1, N - 5) {
f[0][i] = max(f[0][i], f[0][i - 1]);
}
rep(i, 1, 20) {
rep(j, 0, N - 5) {
if(f[i - 1][j] == -1) continue;
f[i][j] = f[i - 1][f[i - 1][j]];
}
}
while(q--) {
read(l);
read(r);
int ans(0);
drp(i, 20, 0) {
if(f[i][l]!=-1&&f[i][l]<r) {
ans|=(1<<i);
l=f[i][l];
}
}
if(f[0][l] < r) out(-1, '\n');
else
out(ans + 1, '\n');
}
return 0;
}