Problem:
Score : 600 points

Problem Statement

There is a grid of squares with H+1 horizontal rows and W vertical columns.

You will start at one of the squares in the top row and repeat moving one square right or down. However, for each integer i from 1 through H, you cannot move down from the A_i-th, (A_i + 1)-th, \ldots, B_i-th squares from the left in the i-th row from the top.

For each integer k from 1 through H, find the minimum number of moves needed to reach one of the squares in the (k+1)-th row from the top. (The starting square can be chosen individually for each case.) If, starting from any square in the top row, none of the squares in the (k+1)-th row can be reached, print -1 instead.

Constraints

1 \leq H,W \leq 2\times 10^5

1 \leq A_i \leq B_i \leq W

Input

Input is given from Standard Input in the following format:

H W
A_1 B_1
A_2 B_2
:
A_H B_H

Output

Print H lines. The i-th line should contain the answer for the case k=i.

Sample Input 1

4 4
2 4
1 1
2 3
2 4

Sample Output 1

1
3
6
-1

Let (i,j) denote the square at the i-th row from the top and j-th column from the left.

For k=1, we need one move such as (1,1) → (2,1).

For k=2, we need three moves such as (1,1) → (2,1) → (2,2) → (3,2).

For k=3, we need six moves such as (1,1) → (2,1) → (2,2) → (3,2) → (3,3) → (3,4) → (4,4).

For k=4, it is impossible to reach any square in the fifth row from the top.

Solution in C++ (GCC 9.2.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>

using namespace std;
#define int long long
typedef long long ll;
typedef long double Double;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

// chmax, chmin
template<class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}

template<class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}

// RMQ + range_add
struct RMQ {
    using value_type = long long;

    static value_type id() { return (long long)(1e18); }

    static value_type op(const value_type &l, const value_type &r) {
        return std::min(l, r);
    }
};

// LeftHandSide
struct LazyEval {
    using value_type = long long;

    static value_type op(const value_type &l, const value_type &r) { return l + r; }
};

struct RangeUpdateRMQ {
    using Monoid = RMQ;
    using Update = LazyEval;
    using value_type = typename Monoid::value_type;
    using update_type = typename Update::value_type;

    static value_type evaluate(const update_type &update, const value_type &r) {
        return update + r;
    }
};

int log2ceil(int n) {
    --n;
    n |= n >> 16;
    n |= n >> 8;
    n |= n >> 4;
    n |= n >> 2;
    n |= n >> 1;
    return n + 1;
}


template<typename Struct>
class SegmentTreeLazy {
public:
    using Monoid = typename Struct::Monoid;
    using Update = typename Struct::Update;
    using value_type = typename Struct::value_type;
    using update_type = typename Struct::update_type;

private:
    const int n;
    std::vector<value_type> data;
    std::vector<update_type> lazy;
    std::vector<bool> flag;

    void lazyset(int node, const update_type &update) {
        if (node < n) {
            if (flag[node]) {
                lazy[node] = Update::op(update, lazy[node]);
            } else {
                lazy[node] = update;
                flag[node] = true;
            }
        }
        data[node] = Struct::evaluate(update, data[node]);
    }

    void evaluate(int node) {
        if (!flag[node]) return;
        flag[node] = false;
        lazyset(node * 2 + 0, lazy[node]);
        lazyset(node * 2 + 1, lazy[node]);
    }

    void update_sub(int l, int r, int node, int lb, int ub,
                    const update_type &update) {
        if (ub <= l || r <= lb) {
            return;
        }
        if (l <= lb && ub <= r) {
            lazyset(node, update);
            return;
        }
        evaluate(node);
        const int mid = (lb + ub) / 2;
        update_sub(l, r, node * 2 + 0, lb, mid, update);
        update_sub(l, r, node * 2 + 1, mid, ub, update);
        data[node] = Monoid::op(data[node * 2 + 0], data[node * 2 + 1]);
    }

    value_type query_sub(int l, int r, int node, int lb, int ub) {
        if (ub <= l || r <= lb) return Monoid::id();
        if (l <= lb && ub <= r) {
            return data[node];
        }
        evaluate(node);
        const int mid = (lb + ub) / 2;
        value_type lval = query_sub(l, r, node * 2 + 0, lb, mid);
        value_type rval = query_sub(l, r, node * 2 + 1, mid, ub);
        return Monoid::op(lval, rval);
    }

public:
    SegmentTreeLazy(int count, const value_type &init = Monoid::id()) :
            n(log2ceil(count)), data(n * 2), lazy(n), flag(n, false) {
        fill(begin(data) + n, end(data), init);
        for (int i = n - 1; i >= 1; i--) {
            data[i] = Monoid::op(data[i * 2 + 0], data[i * 2 + 1]);
        }
    };

    void update(int l, int r, const update_type &f) {

        update_sub(l, r, 1, 0, n, f);
    }

    value_type query(int l, int r) {
        return query_sub(l, r, 1, 0, n);

    }
};


template<class Monoid>
class SegmentTree {
public:
    using value_type = typename Monoid::value_type;
    using update_type = typename Monoid::value_type;

private:
    const int size_, n;
    std::vector<value_type> data;

public:
    SegmentTree(const std::vector<value_type> &vec) :
            size_(vec.size()), n(log2ceil(size_)), data(n * 2, Monoid::id()) {
        std::copy(begin(vec), end(vec), begin(data) + n);
        for (int i = n - 1; i >= 0; --i) {
            data[i] = Monoid::op(data[i * 2 + 0], data[i * 2 + 1]);
        }
    }

    SegmentTree(const int count, const value_type &value = Monoid::id()) :
            SegmentTree(std::vector<value_type>(count, value)) {}

    int size() const { return size_; }

    void update(int pos, const value_type &value) {
        assert(0 <= pos && pos < size_);  // assertion
        data[pos += n] = value;
        while (pos /= 2) {
            data[pos] = Monoid::op(data[pos * 2], data[pos * 2 + 1]);
        }
    }

    // セグメント木の区間 [l, r) を演算 Monoid::op (⋅⋅) で畳み込んだ値を返す． すなわち，al⋅al+1⋅…⋅ar−1al⋅al+1⋅…⋅ar−1 を返す． l=rl=r の場合は Monoid::id() を返す．
    value_type query(int l, int r) const {
        assert(0 <= l && l <= r && r <= size_);  // assertion
        l += n;
        r += n;
        value_type res1 = Monoid::id(), res2 = Monoid::id();
        while (l < r) {
            if (l & 1) res1 = Monoid::op(res1, data[l++]);
            if (r & 1) res2 = Monoid::op(data[--r], res2);
            l >>= 1;
            r >>= 1;
        }
        return Monoid::op(res1, res2);
    }
};

void solve(long long H, long long W, std::vector<long long> A,
           std::vector<long long> B) {
    for (auto &&i : A) {
        i--;
    }

    SegmentTreeLazy<RangeUpdateRMQ> rmq(W);
    SegmentTreeLazy<RangeUpdateRMQ> diffRmq(W);


    rmq.update(0, W, -(long long)(1e18));

    diffRmq.update(0, W, -(long long)(1e18));
    for (int j = 0; j < W; j++) {
        diffRmq.update(j, j + 1, -j);
    }

    long long ans = 1e18;



    for (int i = 0; i < H; i++) {
        if (i > 0) {
            auto v = rmq.query(B[i], B[i]+1);
            rmq.update(B[i], B[i]+1, -v);

            diffRmq.update(B[i], B[i] + 1, -diffRmq.query(B[i], B[i] + 1));

            rmq.update(B[i], B[i] + 1, B[i] + diffRmq.query(0, B[i]));
            diffRmq.update(B[i], B[i] + 1, rmq.query(B[i], B[i + 1]) - B[i]);
        }
//        for (int j = 0; j < W; j++)
//            cout << rmq.query(j, j + 1) << " ";
//        cout << endl;

        rmq.update(0, W, 1);
        rmq.update(A[i], B[i], 1000000ll);
        diffRmq.update(0, W, 1);
        diffRmq.update(A[i], B[i], 1000000ll);

//        for (int j = 0; j < W; j++)
//            cout << rmq.query(j, j + 1) << " ";
//        cout << endl;
//
        if( rmq.query(0, W) < 1000000 ) {
            cout << rmq.query(0, W) << endl;
        }else{
            cout << -1 << endl;
        }
//
//        cout << "=====" << endl;

    }

}

signed main() {
    long long H;
    scanf("%lld", &H);
    long long W;
    scanf("%lld", &W);
    std::vector<long long> A(H);
    std::vector<long long> B(H);
    for (int i = 0; i < H; i++) {
        scanf("%lld", &A[i]);
        scanf("%lld", &B[i]);
    }
    solve(H, W, std::move(A), std::move(B));
    return 0;
}