題目鏈接:
https://codeforces.ml/contest/1175/problem/E
題目大意:
給出n個區間,每次詢問區間[x,y]最少需要多少個區間覆蓋(必須連續即[1,3],[4,5]覆蓋不了[1,5] 因爲[3,4]未完全覆蓋)
如果不可覆蓋則輸出-1
題目思路:
這種區間詢問問題,又無法使用數據結構時,考慮倍增解法
倍增也是基於貪心的思路之上
若用f[i][k]表示i開始用1<<k個區間能夠覆蓋到的最遠點
那麼就滿足題意中的最少了。
如果確定由i開始1個區間可以到達的最遠點
那麼後面就好說了。
怎麼確定一個區間到達的最遠點?
這個地方網上的處理方法令我很迷惑,所以我按照自己處理方法。
第一是考慮線段樹:
[x,y]區間的影響即爲,[x,y]的最大值更新爲y
這樣就可以使用線段樹直接區間更新、區間最大值查詢即可
第二考慮離散化+mutilset
這個靈感來源於之前的一個離散化例題
存一下區間,用set記錄當前最大值
處理好f[i][0]以後
就可以根據lca的思想,無限逼近正確答案的下方
最後輸出正確答案+1即可
Code:
線段樹的.
/*** keep hungry and calm CoolGuang!***/
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=6e5+6;
const int mod=100000000;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
int f[maxn][21];///f[i][k] 表示 從i節點開始一個區間可以覆蓋到的最大值
int vis[maxn];
struct node{
int l,r;
int w,lazy;
}t[maxn*4];
void push(int k){
t[k].w = max(t[k<<1].w,t[k<<1|1].w);
}
void build(int k,int l,int r){
t[k].l = l;t[k].r = r;
t[k].lazy = 0;
if(l==r){
t[k].w = 0;
return ;
}
int mid = (l+r)/2;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
push(k);
}
void down(int k){
t[k<<1].w = max(t[k].lazy,t[k<<1].w);
t[k<<1|1].w = max(t[k].lazy,t[k<<1|1].w);
t[k<<1].lazy = max(t[k].lazy,t[k<<1].lazy);
t[k<<1|1].lazy = max(t[k].lazy,t[k<<1|1].lazy);
t[k].lazy = 0;
}
void update(int k,int x,int y,int w){
if(x<=t[k].l&&y>=t[k].r){
t[k].w = max(t[k].w,w);
t[k].lazy = max(t[k].lazy,w);
return ;
}
down(k);
int mid = (t[k].l+t[k].r)/2;
if(x<=mid) update(k<<1,x,y,w);
if(y>mid) update(k<<1|1,x,y,w);
push(k);
}
int Getpos(int k,int pos){
if(t[k].l == t[k].r){
return t[k].w;
}
down(k);
int mid = (t[k].l+t[k].r)/2;
int ans = 0;
if(pos<=mid) ans = Getpos(k<<1,pos);
else ans = Getpos(k<<1|1,pos);
push(k);
return ans;
}
int main(){
read(n);read(m);
build(1,0,5e5);
for(int i=1;i<=n;i++){
int x,y;scanf("%d%d",&x,&y);
update(1,x,y,y);
}
for(int i=0;i<=5e5;i++){
f[i][0] = Getpos(1,i);
}
for(int k=1;k<=20;k++){
for(int i=0;i<=5e5;i++){
f[i][k] = f[f[i][k-1]][k-1];
}
}
for(int i=1;i<=m;i++){
ll ans = 0;
int x,y;scanf("%d%d",&x,&y);
for(int i=20;i>=0;i--){
if(f[x][i]&&f[x][i]<y){
ans += 1<<i;
x = f[x][i];
}
}
if(f[x][0]<y) printf("-1\n");
else printf("%lld\n",ans+1);
}
return 0;
}
/**
6 12 36
**/