题目链接:
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
**/