【Codeforces 1175E】Minimal Segment Cover | 一个经典倍增问题

题目链接:

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
**/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/106686123
今日推荐