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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章