//#undef DEBUG
#include <bits/stdc++.h>
#include <ext/numeric>
using namespace std; using __gnu_cxx::power;
using ll = long long; using ull = unsigned long long; using ld = long double;
const ll llinf = (1ll<<61)-1; const double eps = 1e-6, ldeps = 1e-9;
const char lf = '\n', splf[] = " \n";
#define all(x) begin(x), end(x)
#define sl(a) int(strlen(a))
#define sz(a) int(a.size())
#define TCC template<class C
struct Dbg { static constexpr auto &os = cout;   // replace by cerr in interactive.
#define ENI typename enable_if<
#define DTOR , Dbg&>::type operator<<
#define RIS return *this
TCC> static auto o(C *x)->decltype(os << *x, 0);
TCC> static char o(...);
TCC> ENI sizeof o<C>(0)!=1 DTOR(const C &x) {os<<x; RIS;}
TCC> Dbg &dump(C b, C e) {
    int ii = 0;
    for(C i = (os << "\n[", b); i!=e and ii<26; i++, ii++) *this << ", "+2*(i==b) << *i;
    RIS << ']';
}
TCC> ENI sizeof o<C>(0)==1 DTOR(const C &x) {
    return dump(all(x));
}
TCC, size_t X> ENI !is_same<C, const char>::value DTOR(C (&x)[X]) {
    return dump(all(x));
}
TCC, class D> Dbg &operator<<(const pair<C, D> &x) {RIS<<'{'<<x.first<<", "<<x.second<<'}';}
Dbg &operator<<(ostream&(*x)(ostream&)) { os << x; RIS; }
} dbg;
void err(istringstream *iss) { delete iss; }
TCC, class... Args> void err(istringstream *iss, const C &val, const Args &... args) {
    string name; *iss >> name; if (name.back()==',') name.pop_back();
    dbg << name << " = " << val << "; ", err(iss, args...);
}
#ifdef DEBUG
#define bug(args...) dbg << __LINE__ << ": ", err(new istringstream(#args), args), dbg << endl
#define cbug(a, args...) if (a) bug(args);
#else
#define bug(args...) void()
#define cbug(a, args...)
#endif
#define ASSERT(a, o, b, args...) if (!((a)o(b))) bug(a, b, ##args), assert((a)o(b));
int T = 1, Q, cn;
const int inf = 1000000007, mxn = 200005;

// In case you ever need l, r of update / query, keep l,r in node.t, in cmbn l = ls.l, r = rs.r, change in query functions.
struct node {   // Try to use as less segtrees as possible for cache, but maybe avoid merging unrelateds.
/*
Caution: queryIndex is combiner of all ancestors, lazy without propagation.
*/
    static const bool isLazy = 1;   // when lazy, can't use updateIndex or queryIndex.
    static constexpr ll RESET = inf;  // base value for query. For using pair t = value of RESET, not RESET;
    static constexpr ll NOLAZY = -1; // a value that either doesn't affect update, or it is never used to update,
                                    // const must instead constexpr in pair, otherwise compiles locally but not in CF

    ll t = RESET/*MUST*/, lazy = NOLAZY;    // if there is no lazy, static update's val type lazy, similar type for NOLAZY;

    void cmbn(node l, node r) { t = min(l.t,r.t);/*t.cmbn(l.t, r.t);*/ }    // l or r can be itself, so no reference

    void assignLeaf(int idx) { t=idx? 0: inf;/*if (idx<mxn) t = a[idx]*/; }  // check arr size

    void upd(const decltype(lazy) &val, int span) { // called from updateIndex too with span==1.
        t = val;
        if (isLazy && span>1) { /*if (lazy==NOLAZY) lazy = RESET;*/ lazy = val; }
    }
};

template <class T> class SegmentTree//{
{
    int H, N, mnIdx;

    void propagate(int at, int lspan, int rspan) {
        t[at<<1].upd(t[at].lazy, lspan), t[at<<1|1].upd(t[at].lazy+lspan, rspan), t[at].lazy = t[0].lazy;
    }

    void push(int l, int r) {
        if (!T::isLazy) return;
        int h = H, k = 1<<(H-1);
        for (l += N, r += N-1; h; h--, k >>= 1) for (int i = l>>h; i <= r>>h; i++)
            if (t[i].lazy != t[0].lazy) propagate(i, k, k);
    }

#define bacca int mid = (l+r)>>1, lson = at<<1, rson = lson|1;

    void updRng(const int &at, const int &l, const int &r, const int &ul, const int &ur, decltype(T::lazy) &val) {
        if (ul<=l && r<=ur) return t[at].upd(val+(l-ul), r-l+1);  // assign t[at] and/or t[at].lazy
        bacca
        if (T::isLazy && t[at].lazy!=t[0].lazy && l!=r) propagate(at, mid-l+1, r-mid);
        if (!(mid<ul)) updRng(lson, l, mid, ul, ur, val);
        if (!(mid+1>ur)) updRng(rson, mid+1, r, ul, ur, val);
        if (T::isLazy) t[at].cmbn(t[lson], t[rson]);    // assign t[at]
    }

    int srchUtil(const int &at, const int &l, const int &r, const decltype(T::t) &val) {
        if (l==r) return (t[at].t>=val) ? l : N;
        bacca
        if (T::isLazy && t[at].lazy!=t[0].lazy) propagate(at, mid-l+1, r-mid);
        if (t[lson].t>=val) return srchUtil(lson, l, mid, val);
        else return srchUtil(rson, mid+1, r, val-t[lson].t);
    }

#undef bacca

public:
    T *t;   // make vector/bitset if needed to assign/copy.
    SegmentTree(int _n, int _mnIdx = 0) : H(32-__builtin_clz(_n-1)), mnIdx(_mnIdx) {
        N = 1U<<H, t = new T[(N<<1)+3];
    }
    ~SegmentTree() { delete[] t; }

    void build() {    // call iff you can't simply set base value of query to whole t
        for (int i = N; i< (N<<1); i++) t[i].assignLeaf(i-N+mnIdx);
        for (int i = N-1; i; i--) t[i].cmbn(t[i<<1], t[i<<1|1]);
        if (T::isLazy) for (int i = 0; i < N<<1; i++) t[i].lazy = t[0].lazy;
    }

    void reset() {
        if (is_trivially_copyable<T>() and !T::RESET && !T::NOLAZY) memset(t, 0, ((N<<1)+3)*sizeof(T));
        else for (int i = 1; i < N<<1; i++) t[i] = t[0];
    }

    void updateIndex(int idx, const decltype(T::lazy) &val) { idx -= mnIdx;
        for (t[idx += N].upd(val, 1), idx >>= 1; idx>=1; idx >>= 1) t[idx].cmbn(t[idx<<1], t[idx<<1|1]);
    }

    void updateRange(int ul, int ur, decltype(T::lazy) val) { if (ul<=ur) updRng(1, 0, N-1, ul-mnIdx, ur-mnIdx, val); }


// updateRange+queryIndex is actually lazy without propagation, where t itself is lazy, this can't be used when order of
// modifications is important e.g. assign (when lazy with prop. it may have different cmbn function or no cmbn)
    decltype(T::t) queryIndex(int idx) { idx -= mnIdx;
        T ret;
        for (idx += N; idx > 0; idx >>= 1) ret.cmbn(ret, t[idx]);
        return ret.t;
    }

    decltype(T::t) queryRange(int l, int r) { l -= mnIdx, r -= mnIdx;
        r++, push(l, l+1), push(r-1, r);
        T resl, resr;
        for (l += N, r += N; l < r; l >>= 1, r >>= 1) {
            if (l&1) resl.cmbn(resl, t[l++]);
            if (r&1) resr.cmbn(t[--r], resr);
        }
        resl.cmbn(resl, resr);
        return resl.t;
    }

    void pushAll() {
        if (T::isLazy) push(0, N);
        else for (int i = 1; i < N; ++i) t[i<<1].cmbn(t[i], t[i<<1]), t[i<<1|1].cmbn(t[i], t[i<<1|1]), t[i].t = T::RESET;
    }

// returns lower_bound if found, else return st.N+mnIdx. To find upper_bound replace 1st and 3rd line's >= by >.
    int search(decltype(T::t) val) { return srchUtil(1, 0, N-1, val)+mnIdx; }

    T& at(const int &idx) { return t[N+idx-mnIdx]; }

    string to_string(int strt = 0, int nd = 26) {
        if (!strt) strt = mnIdx;
        nd = min(nd, N);
        string ret = "\n";
        for (int i = strt; i <= nd; i++) {
            ret += std::to_string(i) + (" "+(i>=10)) + " " + std::to_string(queryRange(i, i)) + "\n";
        }
        return ret;
    }
};//}

SegmentTree<node> st(mxn, 0); // if mnIdx doesn't match there can be corner case for search

int h,w;
pair<int,int>a[mxn];

signed main() { cin.tie(0)->sync_with_stdio(0); cin.exceptions(cin.failbit); cout.precision(11), cout.setf(ios::fixed);
    //cin >> T;
    auto kase = [&]()->void {   // if T>1, inputAll + resetAll -> solution
        //cout << "Case " << cn << ":";
        st.build();
        cin>>h>>w;
        for(int i=1;i<=h;++i){
            cin>>a[i].first>>a[i].second;
            st.updateRange(a[i].first,a[i].second,st.queryRange(a[i].first-1,a[i].first-1)+1);
            ll ans=i+st.queryRange(1,w);
            cout<<(ans<inf? ans: -1)<<lf;
        }
    };
    while (cn++!=T) kase();
}


Measured memory_bytes: 12944