Problem:
Score : 500 points

Problem Statement

There is an infinitely long street that runs west to east, which we consider as a number line.

There are N roadworks scheduled on this street.
The i-th roadwork blocks the point at coordinate X_i from time S_i - 0.5 to time T_i - 0.5.

Q people are standing at coordinate 0. The i-th person will start the coordinate 0 at time D_i, continue to walk with speed 1 in the positive direction and stop walking when reaching a blocked point.

Find the distance each of the Q people will walk.

Constraints

All values in input are integers.

1 \leq N, Q \leq 2 \times 10^5

0 \leq S_i < T_i \leq 10^9

1 \leq X_i \leq 10^9

0 \leq D_1 < D_2 < ... < D_Q \leq 10^9

If i \neq j and X_i = X_j, the intervals [S_i, T_i) and [S_j, T_j) do not overlap.

Input

Input is given from Standard Input in the following format:

N Q
S_1 T_1 X_1
:
S_N T_N X_N
D_1
:
D_Q

Output

Print Q lines. The i-th line should contain the distance the i-th person will walk or -1 if that person walks forever.

Sample Input 1

4 6
1 3 2
7 13 10
18 20 13
3 4 2
0
1
2
3
5
8

Sample Output 1

2
2
10
-1
13
-1

The first person starts coordinate 0 at time 0 and stops walking at coordinate 2 when reaching a point blocked by the first roadwork at time 2.

The second person starts coordinate 0 at time 1 and reaches coordinate 2 at time 3. The first roadwork has ended, but the fourth roadwork has begun, so this person also stops walking at coordinate 2.

The fourth and sixth persons encounter no roadworks while walking, so they walk forever. The output for these cases is -1.

Solution in C++14 (GCC 5.4.1) (judge verdict: Runtime Error)

#ifndef __LAZY_SEGMENT_TREE_H__
#define __LAZY_SEGMENT_TREE_H__

#include <vector>
#include <algorithm>
#include <limits>
#include <cassert>
#include <iostream>
#include <string>
#include <sstream>

/* TODO: 自身への書き込みを遅延させるタイプとの比較 */
/* コンストラクタや代入をもう少し使いやすくする */

// T: 値型 / U: 作用素型(T に作用させる関数の型)
// Identity(): T の単位元
//  Operate(): T × T -> T ::: T における演算
//    Apply(): U × T -> T ::: U の T への作用
//  Compose(): U × U -> U ::: U における合成
//   Ascend(): U -> U      ::: 根方向への移動で生じる U の変化 (区間に比例するなら 2倍)
//  Descend(): U -> U      ::: 葉方向への移動で生じる U の変化 (区間に比例するなら 1/2倍)

// 要求仕様
//   0. (T, Operate) はモノイド, (U, Compose) は半群
//   1. Apply(Ascend(f), Operate(a, b)) == Operate(Apply(f, a), Apply(f, b)) ::: 分配法則
//   2. Apply(Compose(g, f), a) == Apply(g, Apply(f, a))                     ::: 作用素の合成
//   3. Ascend の逆操作が Descend

// 要確認

/*--- てんぷれ ---*/
struct HogeFrame {
	using T = int;
	using U = int;

	static T Identity() {
		return T();
	}

	static T Operate(const T& a, const T& b) {
		return a + b;
	}

	static T Apply(const U& f, const T& a) {
		return f + a;
	}

	static U Compose(const U& f, const U& g) {
		return f + g;
	}

	static U Ascend(const U& f) {
		return f << 1;
	}

	static U Descend(const U& f) {
		return f >> 1;
	}
};

/*----------------*/

namespace Frame {
	/* 補助構造体 */
	template <class Type>
	struct Sum {
		using T = Type;
		using U = Type;

		static T Identity() {
			return T();
		}

		static T Operate(const T& a, const T& b) {
			return a + b;
		}

		static U Ascend(const U& f) {
			return f << 1;
		}

		static U Descend(const U& f) {
			return f >> 1;
		}
	};

	template <class Type>
	struct Minimum {
		using T = Type;
		using U = Type;

		static T Identity() {
			return std::numeric_limits<T>::max();
		}

		static T Operate(const T& a, const T& b) {
			return std::min(a, b);
		}

		static U Ascend(const U& f) {
			return f;
		}

		static U Descend(const U& f) {
			return f;
		}
	};

	template <class Type>
	struct Maximum {
		using T = Type;
		using U = Type;

		static T Identity() {
			return std::numeric_limits<T>::min();
		}

		static T Operate(const T& a, const T& b) {
			return std::max(a, b);
		}

		static U Ascend(const U& f) {
			return f;
		}

		static U Descend(const U& f) {
			return f;
		}
	};

	template <class Type>
	struct Assign {
		using T = Type;
		using U = Type;

		static T Apply(const U& f, const T& a) {
			return f;
		}

		static U Compose(const U& f, const U& g) {
			return f;
		}
	};

	template <class Type>
	struct Add {
		using T = Type;
		using U = Type;

		static T Apply(const U& f, const T& a) {
			return f + a;
		}

		static U Compose(const U& f, const U& g) {
			return f + g;
		}
	};

	template <class Type, class Operation, class Application>
	struct BasicFrame {
		using T = Type;
		using U = Type;

		static T Identity() {
			return Operation::Identity();
		}

		static T Operate(const T& a, const T& b) {
			return Operation::Operate(a, b);
		}

		static T Apply(const U& f, const T& a) {
			return Application::Apply(f, a);
		}

		static U Compose(const U& f, const U& g) {
			return Application::Compose(f, g);
		}

		static U Ascend(const U& f) {
			return Operation::Ascend(f);
		}

		static U Descend(const U& f) {
			return Operation::Descend(f);
		}
	};

	/* 以下を LazySegmentTree のテンプレート引数にする */
	template <class T>
	using AddSum = BasicFrame<T, Sum<T>, Add<T>>;
	template <class T>
	using AddMinimum = BasicFrame<T, Minimum<T>, Add<T>>;
	template <class T>
	using AddMaximum = BasicFrame<T, Maximum<T>, Add<T>>;
	template <class T>
	using AssignSum = BasicFrame<T, Sum<T>, Assign<T>>;
	template <class T>
	using AssignMinimum = BasicFrame<T, Minimum<T>, Assign<T>>;
	template <class T>
	using AssignMaximum = BasicFrame<T, Maximum<T>, Assign<T>>;
}

/* 遅延伝搬セグメント木
 * pos は節点の番号
 * left, right は利用する側から見た添字(もともとの配列における添字) */
template <class Frame>
class LazySegmentTree {
public:
	using T = typename Frame::T;
	using U = typename Frame::U;
	
private:
	int level_m;					// 段数 - 1
	int size_m;						// 1 << level_m
	std::vector<T> arr_m;			// 値配列
	std::vector<U> lazy_m;			// 遅延配列
	std::vector<bool> changed_m;	// 遅延配列が更新されたかどうか

public:
	LazySegmentTree(int level);
	LazySegmentTree(int level, const T& initial_val);
	LazySegmentTree(const std::vector<T>& arr);

private:
	static size_t Left(int pos);
	static size_t Right(int pos);
	static int Level(size_t size);
	void Build();

	void Modify(size_t pos, const U& operation);
	void Evaluate(size_t pos);
	void Propagate(size_t pos);
	void Reflect(size_t pos);
public:
	void Update(size_t left, size_t right, const U& operation);
	T Query(size_t left, size_t right);

private:
	static const int DEFAULT = -1;
public:
	void Debug(int level = DEFAULT, int cell_width = 4) const;
};

/* 1 << level 要素の遅延伝搬セグメント木を作成
 * 遅延配列は葉には必要ないので、その分の領域は確保しないことに注意 */
template<class Frame>
LazySegmentTree<Frame>::LazySegmentTree(int level)
	: level_m(level), size_m(1 << level),
	arr_m(2 * size_m, Frame::Identity()), lazy_m(size_m), changed_m(size_m) {
}

template <class Frame>
LazySegmentTree<Frame>::LazySegmentTree(int level, const T& initial_val)
	: LazySegmentTree(level) {
	std::fill(arr_m.begin() + size_m, arr_m.end(), initial_val);
	Build();
}

template <class Frame>
LazySegmentTree<Frame>::LazySegmentTree(const std::vector<T>& arr)
	: LazySegmentTree(Level(arr.size())) {
	std::copy(arr.begin(), arr.end(), arr_m.begin() + size_m);
	Build();
}

/* 左の子の添字を取得 */
template <class Frame>
inline size_t LazySegmentTree<Frame>::Left(int pos) {
	return pos << 1;
}

/* 右の子の添字を取得 */
template <class Frame>
inline size_t LazySegmentTree<Frame>::Right(int pos) {
	return (pos << 1) | 1;
}

/* size から必要な level を計算 (level = (int)log2(size - 1) + 1) */
template<class Frame>
inline int LazySegmentTree<Frame>::Level(size_t size) {
	assert(size < 0x80000000);
	if (size == 0) return 0;
	
	size_t base = 1;
	int cnt = 0;
	while (base < size) {
		base <<= 1;
		++cnt;
	}
	return cnt;
}

/* 全要素を再計算 */
template <class Frame>
inline void LazySegmentTree<Frame>::Build() {
	for (size_t pos = size_m - 1; pos > 0; --pos) {
		arr_m[pos] = Frame::Operate(arr_m[Left(pos)], arr_m[Right(pos)]);
	}
}

/* pos 番目の節点に operation を作用させる */
template <class Frame>
void LazySegmentTree<Frame>::Modify(size_t pos, const U& operation) {
	arr_m[pos] = Frame::Apply(operation, arr_m[pos]);		// 値の更新
	if (pos < size_m) {
		if (changed_m[pos]) {		// 遅延配列の更新
			lazy_m[pos] = Frame::Compose(operation, lazy_m[pos]);	
		} else {
			lazy_m[pos] = operation;
		}
		changed_m[pos] = true;
	}
}

/* pos 番目の節点の遅延配列の値を子に伝搬させる */
template <class Frame>
void LazySegmentTree<Frame>::Evaluate(size_t pos) {
	assert(pos < size_m);
	if (!changed_m[pos]) return;

	Modify(Left(pos), Frame::Descend(lazy_m[pos]));
	Modify(Right(pos), Frame::Descend(lazy_m[pos]));
	changed_m[pos] = false;
}

/* pos 番目の接点まで根から遅延配列の値を伝搬させる */
template <class Frame>
void LazySegmentTree<Frame>::Propagate(size_t pos) {
	assert(pos >= size_m);
	for (int k = level_m; k > 0; --k) {
		Evaluate(pos >> k);
	}
}

/* pos 番目の接点の祖先の値を再計算 */
template <class Frame>
void LazySegmentTree<Frame>::Reflect(size_t pos) {
	while (pos > 1) {
		pos >>= 1;
		Evaluate(pos);
		arr_m[pos] = Frame::Operate(arr_m[Left(pos)], arr_m[Right(pos)]);
	}
}

/* 区間 [left, right) に属する要素に operation を作用させる(更新クエリ) */
template <class Frame>
void LazySegmentTree<Frame>::Update(size_t left, size_t right, const U& operation) {
	size_t tmp_l = left + size_m;
	size_t tmp_r = right + size_m;
	Propagate(tmp_l);
	Propagate(tmp_r - 1);

	size_t l = tmp_l;
	size_t r = tmp_r;
	U op = operation;
	while (l < r) {
		if (l & 1) Modify(l++, op);
		if (r & 1) Modify(--r, op);
		op = Frame::Ascend(op);
		l >>= 1;
		r >>= 1;
	}
	Reflect(tmp_l);
	Reflect(tmp_r - 1);
}

/* [left, right) に属する全要素の(指定した演算に関する)積をとる(求値クエリ) */
template <class Frame>
typename LazySegmentTree<Frame>::T LazySegmentTree<Frame>::Query(size_t left, size_t right) {
	size_t tmp_l = left + size_m;
	size_t tmp_r = right + size_m;
	Propagate(tmp_l);
	Propagate(tmp_r - 1);
	size_t l = tmp_l;
	size_t r = tmp_r;

	T ret_l = Frame::Identity();
	T ret_r = Frame::Identity();
	while (l < r) {
		if (l & 1) ret_l = Frame::Operate(ret_l, arr_m[l++]);
		if (r & 1) ret_r = Frame::Operate(arr_m[--r], ret_r);
		l >>= 1;
		r >>= 1;
	}
	return Frame::Operate(ret_l, ret_r);
}

/* デバッグ出力用; level = -1 とすると全要素出力 */
template <class Frame>
void LazySegmentTree<Frame>::Debug(int level, int cell_width) const {
	/* 値 value を幅 max_length になるように成形して文字列化 */
	auto to_fixed = [](const std::string& str, int max_length) -> std::string {
		std::string output;
		if (str.size() > max_length) {
			for (int i = 0; i < max_length; ++i) {
				output += '#';
			}
		} else {
			const int remain_length = max_length - str.size();
			const int right_blank = remain_length / 2;
			const int left_blank = remain_length - right_blank;
			for (int i = 0; i < left_blank; ++i) {
				output += ' ';
			}
			output += str;
			for (int i = 0; i < right_blank; ++i) {
				output += ' ';
			}
		}
		return output;
	};

	auto to_str = [](const auto& value) -> std::string {
		std::ostringstream ost;
		ost << value;
		return ost.str();
	};

	// デフォルト値への対処
	if (level == DEFAULT) {
		level = level_m;
	}

	if (level > level_m) {
		level = level_m;
	}

	std::vector<std::string> output_strs;
	for (int lev = 0; lev <= level_m; ++lev) {
		const int front = size_m >> lev;
		std::string output_arr;
		output_arr += '|';
		for (int i = 0; i < (1 << (level_m - lev)); ++i) {
			std::string str = to_str(arr_m[front + i]);
			output_arr += to_fixed(str, cell_width);
			output_arr += '|';
		}

		// 遅延配列は葉には存在しないので葉でない場合のみ
		if (lev > 0) {
			std::string output_lazy;
			output_lazy += '|';
			for (int i = 0; i < (1 << (level_m - lev)); ++i) {
				// changed == false のときは遅延配列の値は無意味なので "null" と表示させる
				std::string str = changed_m[front + i] ? to_str(lazy_m[front + i]) : "null";
				output_lazy += to_fixed(str, cell_width);
				output_lazy += '|';
			}

			// あとで反転させるので逆順に入れる
			output_strs.push_back(output_lazy);
		}
		output_strs.push_back(output_arr);

		cell_width = cell_width * 2 + 1;
	}

	reverse(output_strs.begin(), output_strs.end());
	for (const std::string& output : output_strs) {
		std::cout << output << std::endl;
	}
}

#endif
#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <utility>
#include <algorithm>
#include <functional>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <limits>
#include <numeric>
#include <valarray>
#include <fstream>

using namespace std;
typedef unsigned int uint;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL, LL> PP;
#define REP(i, a, n) for(LL i = (a), i##_max = (n); i < i##_max; ++i)
#define REM(i, a, n) for(LL i = (LL)(n) - 1, i##min = (a); i >= i##min; --i)
#define ALL(arr) (arr).begin(), (arr).end()
#define FLOAT fixed << setprecision(16)
#define SPEEDUP {cin.tie(NULL); ios::sync_with_stdio(false);}
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
template <class T, class U>
istream& operator>>(istream& ist, pair<T, U>& right) { return ist >> right.first >> right.second; }
template <class T, class U>
ostream& operator<<(ostream& ost, const pair<T, U>& right) { return ost << right.first << ' ' << right.second; }
template <class T, class TCompatible, size_t N>
void Fill(T(&dest)[N], const TCompatible& val) { fill(dest, dest + N, val); }
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T(&dest)[M][N], const TCompatible& val) { for (int i = 0; i < M; ++i) Fill(dest[i], val); }
template<class T>
T Compare(T left, T right) { return left > right ? 1 : (left < right ? -1 : 0); }
istream& Ignore(istream& ist) { string s; ist >> s; return ist; }
bool Inside(int i, int j, int h, int w) { return i >= 0 && i < h && j >= 0 && j < w; }
template <class T>
T Next() { T buf; cin >> buf; return buf; }

#ifdef ONLY_MY_ENVIR
#include "IntMod.h"
#include "BinaryMatrix.h"
#include "BIT.h"
#include "Factorization.h"
#include "FlowSolver.h"
#include "Graph.h"
#include "LazySegmentTree.h"
#include "Math.h"
#include "Matrix.h"
#include "MinMax.h"
#include "Position.h"
#include "Range.h"
#include "Rational.h"
#include "SegmentTree.h"
#include "SegmentTree2D.h"
#include "SuffixArray.h"
#include "Tree.h"
#include "UnionFind.h"
#endif

#ifdef __GNUC__
typedef __int128 LLL;
istream& operator>> (istream& ist, __int128& val) { LL tmp;  ist >> tmp; val = tmp; return ist; }
ostream& operator<< (ostream& ost, __int128 val) { LL tmp = val; ost << tmp; return ost; }
#endif

#if 1234567891
#include <array>
#include <random>
#include <unordered_set>
#include <unordered_map>
template<typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T> >;
// template <class T>
// auto Is(const T& value) { return [value](const auto& comparand) -> bool { return comparand == value; }; }
#endif

int N, Q;
int S[200000];
int T[200000];
int X[200000];
int D[200000];

struct MinFrame {
	using T = int;
	using U = int;

	static T Identity() {
		return INF;
	}

	static T Operate(const T& a, const T& b) {
		return min(a, b);
	}

	static T Apply(const U& f, const T& a) {
		return min(f, a);
	}

	static U Compose(const U& f, const U& g) {
		return min(f, g);
	}

	static U Ascend(const U& f) {
		return f;
	}

	static U Descend(const U& f) {
		return f;
	}
};


int main() {
	cin >> N >> Q;
	REP(i, 0, N) {
		cin >> S[i] >> T[i] >> X[i];
	}

	REP(j, 0, Q) {
		cin >> D[j];
	}

	std::vector<int> v(Q, INF);
	LazySegmentTree<MinFrame> seg(v);
	REP(i, 0, N) {
		int l = lower_bound(D, D + Q, S[i] - X[i]) - D;
		int r = lower_bound(D, D + Q, T[i] - X[i]) - D;
		seg.Update(l, r, X[i]);
	}

	REP(j, 0, Q) {
		int ans = seg.Query(j, j + 1);
		if (ans == INF) {
			cout << -1 << endl;
		} else {
			cout << ans << endl;
		}
	}

	return 0;
}