思路:考虑一个暴力的过程:一定是从r出发取覆盖r且左边界最小的线段,不断重复这个过程。
那么可以采取倍增预处理
d
p
i
j
dp_{ij}
dpij表示从j开始取了
2
i
2^i
2i个线段的左边界。初始
d
p
0
,
j
dp_{0,j}
dp0,j等于覆盖j的所有线段中左边界的最小值。
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
int n,m;
pair<int,int>a[N];
int l[N];
struct uzi{
int l,r;
}p[N];
int dp[20][N];
int main() {
ios::sync_with_stdio(false);
cin>>n>>m;memset(l,-1,sizeof l);
for(int i=1;i<=n;i++)cin>>a[i].fi>>a[i].se;
sort(a+1,a+1+n);
int index=1;
priority_queue<pair<int,int>>Q;
for(int i=0;i<=500000;i++){
while(index<=n && a[index].fi ==i){
Q.push({-a[index].fi,a[index].se});
index++;
}
while(!Q.empty() &&Q.top().se<i)Q.pop();
if(!Q.empty())l[i]=-Q.top().fi,dp[0][i]=l[i];
else dp[0][i]=-1;
}
for(int i=1;i<=19;i++){
for(int j=0;j<=500000;j++){
if(dp[i-1][j]==-1)dp[i][j]=-1;
else dp[i][j]=dp[i-1][dp[i-1][j]];
}
}
for(int i=1;i<=m;i++){
cin>>p[i].l>>p[i].r;
int now=p[i].r;
if(l[now]==-1){
cout<<-1<<'\n';
continue;
}
int need=0;
for(int j=19;j>=0;j--){
if(dp[j][now]>p[i].l){
need+=1<<j;
now=dp[j][now];
}
}
if(now==-1||dp[0][now]>p[i].l)cout<<-1<<'\n';
else cout<<need+1<<'\n';
}
return 0;
}