2376:Cleaning Shifts

keyword

greedy C++

概要

N(<25000)個の区間が与えられ、1からT(<10^6)を被覆するのに必要な最小の個数を求める問題。
区間スケジューリング問題によく似た何か。今選べる開始時刻を持った区間の内、終了時刻が最も遅いものを選べば良い。開始時刻でソートしておけば計算量を落とせる。

int main(){
    static ll ranges[25002];
    int i, j, n, t, from, to, ans=0;
    ll mask = (1<<30)-1;
    scanf("%d%d",&n,&t);

    REP(i,n){
        scanf("%d%d",&from, &to);
        ranges[i] = ((ll)from<<30) + to;
    }
    sort(ranges,ranges+n);

    from = 1;
    to = 0;
    i = 0;
    bool updated;
    while(1){
        updated = false;
        for(;i<n && (int)(ranges[i]>>30) <= from;i++){
            to = max(to,(int)(ranges[i]&mask));
            updated = true;
        }
        ans++;
        if(to >= t){
            printf("%d\n",ans);
            break;
        }
        if(i==n || !updated){
            printf("-1\n");
            break;
        }
        from = to + 1;
    }

    return 0;
}