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<i32> = line.trim().split(" ").map(|val| val.parse().unwrap()).collect();
	let (h, w) = (tmp[0],tmp[1]);

	// 現在行で、ある場所からスタートする時の、前行まででの初期位置？を格納？
	// 不要なスタート地点は都度抜いていくが、
	// 最初は全ての場所(W個)をスタート地点にEntry
	let mut start_and_init = BTreeSet::new();
	// let mut set_answers = BTreeSet::new();
	// let mut map_answers = BTreeMap::new();
	let mut answers = BTreeSet::new();
	for w_ in 0..w {
		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 : i32 = -1;
		// println!("{}: {}", wall_left, wall_right_plus_one);

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

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

		// for (start_pos,init_pos) in tmp.iter() {
		// 	start_and_init.remove( &(*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の中で(前の行で)一番右の初期位置が入っているはず
			// この行では、前の行で、なるべく右を初期位置とみなす方が得なので、それを使用。
			answers.insert( (wall_right_plus_one - max_init_pos, wall_right_plus_one) );//wall_right_plus_one - max_init_pos );
			start_and_init.insert((wall_right_plus_one, max_init_pos));
			// println!("startpos={} initpos={}", wall_right_plus_one, max_init_pos);
			// println!("{:?}",answers);
		}

		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);
	}
}