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 Rust (1.42.0) (judge verdict: Accepted)

use std::io;
use std::cmp;
use std::collections::BTreeMap;
use std::collections::BTreeSet;

fn main() {

	let mut line = String::new();

	io::stdin().read_line(&mut line).expect("Failed to read line.");
	let mut tmp : Vec<i64> = line.trim().split(" ").map(|val| val.parse().unwrap()).collect();
	let (h, w) = (tmp[0],tmp[1]);


	// 現在、ある場所からスタートした時に、最終的にどこまで右に行くのかを記録
	// 不要なスタート地点は都度抜いていくが、
	// 最初は全ての場所(W個)をスタート地点にEntry
	let mut map_start_and_init = BTreeMap::new();
	// let mut set_answers = BTreeSet::new();
	// let mut map_answers = BTreeMap::new();
	let mut answers = BTreeSet::new();	
	for w_ in 0..w {
		map_start_and_init.insert(w_,w_);
		answers.insert((0,w_));	// 欲しいのはfirstだけだが、multiset的な使い方をするために、secondに開始位置格納。。。
	}


	for h_ in 0..h {
		// 行ごとに答えを更新していくスタイル
		line = "".to_string();
		io::stdin().read_line(&mut line).expect("Failed to read line.");
		tmp = line.trim().split(" ").map(|val| val.parse().unwrap()).collect();
		let (wall_left, wall_right_plus_one) = (tmp[0]-1,tmp[1]);
		// 前の行の壁内Entryで一番右まで行ってた位置
		let mut max_init_pos : i64 = -1;
		// println!("{}: {}", wall_left, wall_right_plus_one);

		// 現在のスタート位置のメモから、壁の左から先を切り取り(ここで元のメモからも消滅)
		// let mut in_wall_plus_one = map_start_and_init.split_off(&wall_left);
		// // 元のメモに、切り抜き過ぎた部分(壁の右[+1]列より右)をもう一度つける。。
		// let mut next_wall = in_wall_plus_one.split_off(&(wall_right_plus_one+1));
		// map_start_and_init.append(&mut next_wall);
		let mut tmp : Vec<(i64,i64)> = Vec::new();
		for (&start_pos,&init_pos) in map_start_and_init.range(wall_left..wall_right_plus_one+1) {
			tmp.push( (start_pos,init_pos) );
			// println!("Vec {}: {}", start_pos, init_pos);
		}

		for &( start_pos, init_pos ) in tmp.iter() {
			// 壁のある部分について、Entryを更新する
			// (壁startから、壁END[+1]の場所まで更新するので注意する)
			// 壁のある地点Entryを全部削除(=>すでに抜き出し済み)
			// 壁内の答えもセットで削除
			answers.remove( &(start_pos - init_pos, start_pos) );
			map_start_and_init.remove( &start_pos );
			// 前の行までに作った、行の壁内のEntry中で一番右の場所を取得
			max_init_pos = cmp::max( max_init_pos, init_pos );
			// println!("{}行目 {}: {}", h_+1, start_pos, init_pos);
		}

		if max_init_pos != -1 && wall_right_plus_one < w {
			// 壁内のEntryが更新された場合
			// 壁START〜壁END+1までのEntryは全て削除ずみ
			// それを壁END+1スタートのEntry１つにまとめて再登録する
			// (壁が右まで行っちゃってたら再登録しないので壁内のEntryは全消滅)
			// max_init_posには、壁内にあったEntryの中で(前の行で)一番右まで行ってたやつが入っているはず
			// この行では、前の行で、なるべく右まで行っていたものとみなす方が得なので、それを使用。
			// println!("wall_right_plus_one={}: max_init_pos={}", wall_right_plus_one, max_init_pos);
			answers.insert( (wall_right_plus_one - max_init_pos, wall_right_plus_one ) );//wall_right_plus_one - max_init_pos );
			map_start_and_init.insert(wall_right_plus_one, max_init_pos);
		}

		let mut ans = -1;
		if false == answers.is_empty() {
			// 答えは、消えてないEntry内で右移動した量の最小値
			let min_right_move = answers.iter().next().unwrap().0;
			// let first = set_answers.iter().next();
			ans = min_right_move + (h_+1);
		}

		println!("{}", ans);
	}
}