#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
#define rep(i,a,b) for(int i=(a); i<(b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
using ll = long long;
using ld = long double;
using pii = pair<ll,ll>;
template<class T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
const ld EPS = 1e-28L;
struct Segment {
using S = Segment;
pair<ld,ld> x, y;
explicit Segment(pair<ld, ld> ox, pair<ld, ld> oy) {
if (ox.first > oy.first) swap(ox, oy);
x = ox; y = oy;
}
ld evaluate(ld xv) const {
if (x.first == y.first) return x.second;
ld slope = (x.second - y.second) / (x.first - y.first);
return x.second + (xv - x.first) * slope;
}
ld common_x(S s) const {
ld l = max(x.first, s.x.first);
ld r = min(y.first, s.y.first);
return l + (r - l) / 2.0L;
}
bool operator==(S s) const {
ld xv = common_x(s);
return fabsl(evaluate(xv) - s.evaluate(xv)) < EPS;
}
bool operator<(S s) const {
ld xv = common_x(s);
return !((*this) == s) && evaluate(xv) < s.evaluate(xv);
}
};
static inline ll mygcd(ll a, ll b) {
if (a < 0) a = -a;
if (b < 0) b = -b;
while (b) { ll t = a % b; a = b; b = t; }
return a;
}
struct Fraction {
using F = Fraction;
ll x, y;
explicit Fraction(ll xx=0, ll yy=1) {
if (yy < 0) xx = -xx, yy = -yy;
ll d = mygcd(llabs(xx), llabs(yy));
x = xx / d; y = yy / d;
}
F operator+(F o) const { return F(x*o.y + o.x*y, y*o.y); }
F operator-(F o) const { return F(x*o.y - o.x*y, y*o.y); }
F operator*(F o) const { return F(x*o.x, y*o.y); }
F operator/(F o) const { return F(x*o.y, y*o.x); }
bool operator<(F o) const { return x*o.y < o.x*y; }
bool operator==(F o) const { return x*o.y == o.x*y; }
bool operator<=(F o) const { return (*this) == o || (*this) < o; }
};
struct SegmentInt {
using S = SegmentInt;
pii x, y;
explicit SegmentInt(pii ox, pii oy) {
if (tie(ox.first, ox.second) > tie(oy.first, oy.second)) swap(ox, oy);
x = ox; y = oy;
}
Fraction evaluate(ll xv) const {
if (x.first == y.first) return Fraction(x.second, 1);
Fraction slope = Fraction(x.second - y.second, x.first - y.first);
return Fraction(x.second) + (Fraction(xv) - Fraction(x.first)) * slope;
}
pair<ll,ll> common_x_range(S s) const {
ll l = max(x.first, s.x.first);
ll r = min(y.first, s.y.first);
return {l, r};
}
bool operator==(S s) const {
pair<ll,ll> cr = common_x_range(s);
ll l = cr.first, r = cr.second;
Fraction ta = evaluate(l), tb = evaluate(r);
Fraction sa = s.evaluate(l), sb = s.evaluate(r);
return (ta == sa) && (tb == sb);
}
bool operator<(S s) const {
pair<ll,ll> cr = common_x_range(s);
ll l = cr.first, r = cr.second;
return !((*this) == s) && (evaluate(l) <= s.evaluate(l) && evaluate(r) <= s.evaluate(r));
}
};
static inline int lower_idx_ld(const vector<ld>& v, ld x) {
return int(lower_bound(all(v), x) - v.begin());
}
static inline int lower_idx_ll(const vector<ll>& v, ll x) {
return int(lower_bound(all(v), x) - v.begin());
}
static inline pair<ld,ld> rotate_point(pii p) {
static const ld c = cosl(1.0L), s = sinl(1.0L);
return {p.first * c - p.second * s, p.first * s + p.second * c};
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
if (!(cin >> n >> m)) return 0;
vector<pii> poly(n), points(m);
set<pii> on_vertex;
vector<ll> xs_int; xs_int.reserve(n + m);
rep(i,0,n) {
ll x, y; cin >> x >> y;
poly[i] = {x, y};
on_vertex.insert(poly[i]);
xs_int.push_back(x);
}
vector<int> result(m, -1);
rep(i,0,m) {
ll x, y; cin >> x >> y;
points[i] = {x, y};
if (on_vertex.count(points[i])) result[i] = 1;
xs_int.push_back(x);
}
sort(all(xs_int));
xs_int.erase(unique(all(xs_int)), xs_int.end());
vector<vector<SegmentInt>> add_int(sz(xs_int)), rem_int(sz(xs_int)), vertical_int(sz(xs_int));
vector<vector<pair<pii,int>>> queries_int(sz(xs_int));
rep(i,0,n) {
SegmentInt seg(poly[i], poly[(i+1)%n]);
if (seg.x.first != seg.y.first) {
int a = lower_idx_ll(xs_int, seg.x.first);
int b = lower_idx_ll(xs_int, seg.y.first);
add_int[a].push_back(seg);
rem_int[b].push_back(seg);
} else {
int id = lower_idx_ll(xs_int, seg.x.first);
vertical_int[id].push_back(seg);
}
}
rep(i,0,m) if (result[i] == -1) {
int id = lower_idx_ll(xs_int, points[i].first);
queries_int[id].push_back({points[i], i});
}
Tree<SegmentInt> active_int;
rep(i,0,sz(xs_int)) {
for (auto& seg : rem_int[i]) active_int.erase(seg);
for (auto& qp : queries_int[i]) {
SegmentInt tmp(qp.first, qp.first);
int k = active_int.order_of_key(tmp);
auto it = active_int.find_by_order(k);
if (it != active_int.end() && (*it) == tmp) result[qp.second] = 1;
}
for (auto& seg : add_int[i]) active_int.insert(seg);
}
rep(i,0,sz(xs_int)) {
map<ll, vector<int>> buckets;
for (auto& qp : queries_int[i]) buckets[qp.first.second].push_back(qp.second);
for (auto& seg : vertical_int[i]) {
auto it = buckets.lower_bound(seg.x.second);
while (it != buckets.end() && it->first <= seg.y.second) {
for (int idx : it->second) result[idx] = 1;
++it;
}
}
}
vector<pair<ld,ld>> poly_r(n), pts_r(m);
vector<ld> xs; xs.reserve(n + m);
rep(i,0,n) { poly_r[i] = rotate_point(poly[i]); xs.push_back(poly_r[i].first); }
rep(i,0,m) { pts_r[i] = rotate_point(points[i]); xs.push_back(pts_r[i].first); }
sort(all(xs));
xs.erase(unique(all(xs)), xs.end());
vector<vector<Segment>> addSeg(sz(xs)), remSeg(sz(xs));
vector<vector<pair<pair<ld,ld>,int>>> queries(sz(xs));
rep(i,0,n) {
Segment s(poly_r[i], poly_r[(i+1)%n]);
int a = lower_idx_ld(xs, s.x.first);
int b = lower_idx_ld(xs, s.y.first);
addSeg[a].push_back(s);
remSeg[b].push_back(s);
}
rep(i,0,m) if (result[i] == -1) {
int id = lower_idx_ld(xs, pts_r[i].first);
queries[id].push_back({pts_r[i], i});
}
Tree<Segment> active;
rep(i,0,sz(xs)) {
for (auto& s : remSeg[i]) active.erase(s);
for (auto& qp : queries[i]) {
Segment tmp(qp.first, qp.first);
int k = active.order_of_key(tmp);
result[qp.second] = (k % 2 == 1);
}
for (auto& s : addSeg[i]) active.insert(s);
}
rep(i,0,m) cout << (result[i] ? "YES\n" : "NO\n");
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiNpbmNsdWRlIDxiaXRzL2V4dGMrKy5oPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwp1c2luZyBuYW1lc3BhY2UgX19nbnVfcGJkczsKCiNkZWZpbmUgcmVwKGksYSxiKSBmb3IoaW50IGk9KGEpOyBpPChiKTsgKytpKQojZGVmaW5lIGFsbCh4KSBiZWdpbih4KSwgZW5kKHgpCiNkZWZpbmUgc3ooeCkgKGludCkoeCkuc2l6ZSgpCnVzaW5nIGxsID0gbG9uZyBsb25nOwp1c2luZyBsZCA9IGxvbmcgZG91YmxlOwp1c2luZyBwaWkgPSBwYWlyPGxsLGxsPjsKCnRlbXBsYXRlPGNsYXNzIFQ+CnVzaW5nIFRyZWUgPSB0cmVlPFQsIG51bGxfdHlwZSwgbGVzczxUPiwgcmJfdHJlZV90YWcsIHRyZWVfb3JkZXJfc3RhdGlzdGljc19ub2RlX3VwZGF0ZT47Cgpjb25zdCBsZCBFUFMgPSAxZS0yOEw7CgpzdHJ1Y3QgU2VnbWVudCB7CiAgICB1c2luZyBTID0gU2VnbWVudDsKICAgIHBhaXI8bGQsbGQ+IHgsIHk7CiAgICBleHBsaWNpdCBTZWdtZW50KHBhaXI8bGQsIGxkPiBveCwgcGFpcjxsZCwgbGQ+IG95KSB7CiAgICAgICAgaWYgKG94LmZpcnN0ID4gb3kuZmlyc3QpIHN3YXAob3gsIG95KTsKICAgICAgICB4ID0gb3g7IHkgPSBveTsKICAgIH0KICAgIGxkIGV2YWx1YXRlKGxkIHh2KSBjb25zdCB7CiAgICAgICAgaWYgKHguZmlyc3QgPT0geS5maXJzdCkgcmV0dXJuIHguc2Vjb25kOwogICAgICAgIGxkIHNsb3BlID0gKHguc2Vjb25kIC0geS5zZWNvbmQpIC8gKHguZmlyc3QgLSB5LmZpcnN0KTsKICAgICAgICByZXR1cm4geC5zZWNvbmQgKyAoeHYgLSB4LmZpcnN0KSAqIHNsb3BlOwogICAgfQogICAgbGQgY29tbW9uX3goUyBzKSBjb25zdCB7CiAgICAgICAgbGQgbCA9IG1heCh4LmZpcnN0LCBzLnguZmlyc3QpOwogICAgICAgIGxkIHIgPSBtaW4oeS5maXJzdCwgcy55LmZpcnN0KTsKICAgICAgICByZXR1cm4gbCArIChyIC0gbCkgLyAyLjBMOwogICAgfQogICAgYm9vbCBvcGVyYXRvcj09KFMgcykgY29uc3QgewogICAgICAgIGxkIHh2ID0gY29tbW9uX3gocyk7CiAgICAgICAgcmV0dXJuIGZhYnNsKGV2YWx1YXRlKHh2KSAtIHMuZXZhbHVhdGUoeHYpKSA8IEVQUzsKICAgIH0KICAgIGJvb2wgb3BlcmF0b3I8KFMgcykgY29uc3QgewogICAgICAgIGxkIHh2ID0gY29tbW9uX3gocyk7CiAgICAgICAgcmV0dXJuICEoKCp0aGlzKSA9PSBzKSAmJiBldmFsdWF0ZSh4dikgPCBzLmV2YWx1YXRlKHh2KTsKICAgIH0KfTsKCnN0YXRpYyBpbmxpbmUgbGwgbXlnY2QobGwgYSwgbGwgYikgewogICAgaWYgKGEgPCAwKSBhID0gLWE7CiAgICBpZiAoYiA8IDApIGIgPSAtYjsKICAgIHdoaWxlIChiKSB7IGxsIHQgPSBhICUgYjsgYSA9IGI7IGIgPSB0OyB9CiAgICByZXR1cm4gYTsKfQoKc3RydWN0IEZyYWN0aW9uIHsKICAgIHVzaW5nIEYgPSBGcmFjdGlvbjsKICAgIGxsIHgsIHk7CiAgICBleHBsaWNpdCBGcmFjdGlvbihsbCB4eD0wLCBsbCB5eT0xKSB7CiAgICAgICAgaWYgKHl5IDwgMCkgeHggPSAteHgsIHl5ID0gLXl5OwogICAgICAgIGxsIGQgPSBteWdjZChsbGFicyh4eCksIGxsYWJzKHl5KSk7CiAgICAgICAgeCA9IHh4IC8gZDsgeSA9IHl5IC8gZDsKICAgIH0KICAgIEYgb3BlcmF0b3IrKEYgbykgY29uc3QgeyByZXR1cm4gRih4Km8ueSArIG8ueCp5LCB5Km8ueSk7IH0KICAgIEYgb3BlcmF0b3ItKEYgbykgY29uc3QgeyByZXR1cm4gRih4Km8ueSAtIG8ueCp5LCB5Km8ueSk7IH0KICAgIEYgb3BlcmF0b3IqKEYgbykgY29uc3QgeyByZXR1cm4gRih4Km8ueCwgeSpvLnkpOyB9CiAgICBGIG9wZXJhdG9yLyhGIG8pIGNvbnN0IHsgcmV0dXJuIEYoeCpvLnksIHkqby54KTsgfQogICAgYm9vbCBvcGVyYXRvcjwoRiBvKSBjb25zdCB7IHJldHVybiB4Km8ueSA8IG8ueCp5OyB9CiAgICBib29sIG9wZXJhdG9yPT0oRiBvKSBjb25zdCB7IHJldHVybiB4Km8ueSA9PSBvLngqeTsgfQogICAgYm9vbCBvcGVyYXRvcjw9KEYgbykgY29uc3QgeyByZXR1cm4gKCp0aGlzKSA9PSBvIHx8ICgqdGhpcykgPCBvOyB9Cn07CgpzdHJ1Y3QgU2VnbWVudEludCB7CiAgICB1c2luZyBTID0gU2VnbWVudEludDsKICAgIHBpaSB4LCB5OwogICAgZXhwbGljaXQgU2VnbWVudEludChwaWkgb3gsIHBpaSBveSkgewogICAgICAgIGlmICh0aWUob3guZmlyc3QsIG94LnNlY29uZCkgPiB0aWUob3kuZmlyc3QsIG95LnNlY29uZCkpIHN3YXAob3gsIG95KTsKICAgICAgICB4ID0gb3g7IHkgPSBveTsKICAgIH0KICAgIEZyYWN0aW9uIGV2YWx1YXRlKGxsIHh2KSBjb25zdCB7CiAgICAgICAgaWYgKHguZmlyc3QgPT0geS5maXJzdCkgcmV0dXJuIEZyYWN0aW9uKHguc2Vjb25kLCAxKTsKICAgICAgICBGcmFjdGlvbiBzbG9wZSA9IEZyYWN0aW9uKHguc2Vjb25kIC0geS5zZWNvbmQsIHguZmlyc3QgLSB5LmZpcnN0KTsKICAgICAgICByZXR1cm4gRnJhY3Rpb24oeC5zZWNvbmQpICsgKEZyYWN0aW9uKHh2KSAtIEZyYWN0aW9uKHguZmlyc3QpKSAqIHNsb3BlOwogICAgfQogICAgcGFpcjxsbCxsbD4gY29tbW9uX3hfcmFuZ2UoUyBzKSBjb25zdCB7CiAgICAgICAgbGwgbCA9IG1heCh4LmZpcnN0LCBzLnguZmlyc3QpOwogICAgICAgIGxsIHIgPSBtaW4oeS5maXJzdCwgcy55LmZpcnN0KTsKICAgICAgICByZXR1cm4ge2wsIHJ9OwogICAgfQogICAgYm9vbCBvcGVyYXRvcj09KFMgcykgY29uc3QgewogICAgICAgIHBhaXI8bGwsbGw+IGNyID0gY29tbW9uX3hfcmFuZ2Uocyk7CiAgICAgICAgbGwgbCA9IGNyLmZpcnN0LCByID0gY3Iuc2Vjb25kOwogICAgICAgIEZyYWN0aW9uIHRhID0gZXZhbHVhdGUobCksIHRiID0gZXZhbHVhdGUocik7CiAgICAgICAgRnJhY3Rpb24gc2EgPSBzLmV2YWx1YXRlKGwpLCBzYiA9IHMuZXZhbHVhdGUocik7CiAgICAgICAgcmV0dXJuICh0YSA9PSBzYSkgJiYgKHRiID09IHNiKTsKICAgIH0KICAgIGJvb2wgb3BlcmF0b3I8KFMgcykgY29uc3QgewogICAgICAgIHBhaXI8bGwsbGw+IGNyID0gY29tbW9uX3hfcmFuZ2Uocyk7CiAgICAgICAgbGwgbCA9IGNyLmZpcnN0LCByID0gY3Iuc2Vjb25kOwogICAgICAgIHJldHVybiAhKCgqdGhpcykgPT0gcykgJiYgKGV2YWx1YXRlKGwpIDw9IHMuZXZhbHVhdGUobCkgJiYgZXZhbHVhdGUocikgPD0gcy5ldmFsdWF0ZShyKSk7CiAgICB9Cn07CgpzdGF0aWMgaW5saW5lIGludCBsb3dlcl9pZHhfbGQoY29uc3QgdmVjdG9yPGxkPiYgdiwgbGQgeCkgewogICAgcmV0dXJuIGludChsb3dlcl9ib3VuZChhbGwodiksIHgpIC0gdi5iZWdpbigpKTsKfQpzdGF0aWMgaW5saW5lIGludCBsb3dlcl9pZHhfbGwoY29uc3QgdmVjdG9yPGxsPiYgdiwgbGwgeCkgewogICAgcmV0dXJuIGludChsb3dlcl9ib3VuZChhbGwodiksIHgpIC0gdi5iZWdpbigpKTsKfQpzdGF0aWMgaW5saW5lIHBhaXI8bGQsbGQ+IHJvdGF0ZV9wb2ludChwaWkgcCkgewogICAgc3RhdGljIGNvbnN0IGxkIGMgPSBjb3NsKDEuMEwpLCBzID0gc2lubCgxLjBMKTsKICAgIHJldHVybiB7cC5maXJzdCAqIGMgLSBwLnNlY29uZCAqIHMsIHAuZmlyc3QgKiBzICsgcC5zZWNvbmQgKiBjfTsKfQoKaW50IG1haW4oKSB7CiAgICBpb3M6OnN5bmNfd2l0aF9zdGRpbyhmYWxzZSk7CiAgICBjaW4udGllKG51bGxwdHIpOwoKICAgIGludCBuLCBtOwogICAgaWYgKCEoY2luID4+IG4gPj4gbSkpIHJldHVybiAwOwoKICAgIHZlY3RvcjxwaWk+IHBvbHkobiksIHBvaW50cyhtKTsKICAgIHNldDxwaWk+IG9uX3ZlcnRleDsKICAgIHZlY3RvcjxsbD4geHNfaW50OyB4c19pbnQucmVzZXJ2ZShuICsgbSk7CiAgICByZXAoaSwwLG4pIHsKICAgICAgICBsbCB4LCB5OyBjaW4gPj4geCA+PiB5OwogICAgICAgIHBvbHlbaV0gPSB7eCwgeX07CiAgICAgICAgb25fdmVydGV4Lmluc2VydChwb2x5W2ldKTsKICAgICAgICB4c19pbnQucHVzaF9iYWNrKHgpOwogICAgfQogICAgdmVjdG9yPGludD4gcmVzdWx0KG0sIC0xKTsKICAgIHJlcChpLDAsbSkgewogICAgICAgIGxsIHgsIHk7IGNpbiA+PiB4ID4+IHk7CiAgICAgICAgcG9pbnRzW2ldID0ge3gsIHl9OwogICAgICAgIGlmIChvbl92ZXJ0ZXguY291bnQocG9pbnRzW2ldKSkgcmVzdWx0W2ldID0gMTsKICAgICAgICB4c19pbnQucHVzaF9iYWNrKHgpOwogICAgfQogICAgc29ydChhbGwoeHNfaW50KSk7CiAgICB4c19pbnQuZXJhc2UodW5pcXVlKGFsbCh4c19pbnQpKSwgeHNfaW50LmVuZCgpKTsKCiAgICB2ZWN0b3I8dmVjdG9yPFNlZ21lbnRJbnQ+PiBhZGRfaW50KHN6KHhzX2ludCkpLCByZW1faW50KHN6KHhzX2ludCkpLCB2ZXJ0aWNhbF9pbnQoc3ooeHNfaW50KSk7CiAgICB2ZWN0b3I8dmVjdG9yPHBhaXI8cGlpLGludD4+PiBxdWVyaWVzX2ludChzeih4c19pbnQpKTsKCiAgICByZXAoaSwwLG4pIHsKICAgICAgICBTZWdtZW50SW50IHNlZyhwb2x5W2ldLCBwb2x5WyhpKzEpJW5dKTsKICAgICAgICBpZiAoc2VnLnguZmlyc3QgIT0gc2VnLnkuZmlyc3QpIHsKICAgICAgICAgICAgaW50IGEgPSBsb3dlcl9pZHhfbGwoeHNfaW50LCBzZWcueC5maXJzdCk7CiAgICAgICAgICAgIGludCBiID0gbG93ZXJfaWR4X2xsKHhzX2ludCwgc2VnLnkuZmlyc3QpOwogICAgICAgICAgICBhZGRfaW50W2FdLnB1c2hfYmFjayhzZWcpOwogICAgICAgICAgICByZW1faW50W2JdLnB1c2hfYmFjayhzZWcpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGludCBpZCA9IGxvd2VyX2lkeF9sbCh4c19pbnQsIHNlZy54LmZpcnN0KTsKICAgICAgICAgICAgdmVydGljYWxfaW50W2lkXS5wdXNoX2JhY2soc2VnKTsKICAgICAgICB9CiAgICB9CiAgICByZXAoaSwwLG0pIGlmIChyZXN1bHRbaV0gPT0gLTEpIHsKICAgICAgICBpbnQgaWQgPSBsb3dlcl9pZHhfbGwoeHNfaW50LCBwb2ludHNbaV0uZmlyc3QpOwogICAgICAgIHF1ZXJpZXNfaW50W2lkXS5wdXNoX2JhY2soe3BvaW50c1tpXSwgaX0pOwogICAgfQoKICAgIFRyZWU8U2VnbWVudEludD4gYWN0aXZlX2ludDsKICAgIHJlcChpLDAsc3ooeHNfaW50KSkgewogICAgICAgIGZvciAoYXV0byYgc2VnIDogcmVtX2ludFtpXSkgYWN0aXZlX2ludC5lcmFzZShzZWcpOwogICAgICAgIGZvciAoYXV0byYgcXAgOiBxdWVyaWVzX2ludFtpXSkgewogICAgICAgICAgICBTZWdtZW50SW50IHRtcChxcC5maXJzdCwgcXAuZmlyc3QpOwogICAgICAgICAgICBpbnQgayA9IGFjdGl2ZV9pbnQub3JkZXJfb2Zfa2V5KHRtcCk7CiAgICAgICAgICAgIGF1dG8gaXQgPSBhY3RpdmVfaW50LmZpbmRfYnlfb3JkZXIoayk7CiAgICAgICAgICAgIGlmIChpdCAhPSBhY3RpdmVfaW50LmVuZCgpICYmICgqaXQpID09IHRtcCkgcmVzdWx0W3FwLnNlY29uZF0gPSAxOwogICAgICAgIH0KICAgICAgICBmb3IgKGF1dG8mIHNlZyA6IGFkZF9pbnRbaV0pIGFjdGl2ZV9pbnQuaW5zZXJ0KHNlZyk7CiAgICB9CgogICAgcmVwKGksMCxzeih4c19pbnQpKSB7CiAgICAgICAgbWFwPGxsLCB2ZWN0b3I8aW50Pj4gYnVja2V0czsKICAgICAgICBmb3IgKGF1dG8mIHFwIDogcXVlcmllc19pbnRbaV0pIGJ1Y2tldHNbcXAuZmlyc3Quc2Vjb25kXS5wdXNoX2JhY2socXAuc2Vjb25kKTsKICAgICAgICBmb3IgKGF1dG8mIHNlZyA6IHZlcnRpY2FsX2ludFtpXSkgewogICAgICAgICAgICBhdXRvIGl0ID0gYnVja2V0cy5sb3dlcl9ib3VuZChzZWcueC5zZWNvbmQpOwogICAgICAgICAgICB3aGlsZSAoaXQgIT0gYnVja2V0cy5lbmQoKSAmJiBpdC0+Zmlyc3QgPD0gc2VnLnkuc2Vjb25kKSB7CiAgICAgICAgICAgICAgICBmb3IgKGludCBpZHggOiBpdC0+c2Vjb25kKSByZXN1bHRbaWR4XSA9IDE7CiAgICAgICAgICAgICAgICArK2l0OwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHZlY3RvcjxwYWlyPGxkLGxkPj4gcG9seV9yKG4pLCBwdHNfcihtKTsKICAgIHZlY3RvcjxsZD4geHM7IHhzLnJlc2VydmUobiArIG0pOwogICAgcmVwKGksMCxuKSB7IHBvbHlfcltpXSA9IHJvdGF0ZV9wb2ludChwb2x5W2ldKTsgeHMucHVzaF9iYWNrKHBvbHlfcltpXS5maXJzdCk7IH0KICAgIHJlcChpLDAsbSkgeyBwdHNfcltpXSA9IHJvdGF0ZV9wb2ludChwb2ludHNbaV0pOyB4cy5wdXNoX2JhY2socHRzX3JbaV0uZmlyc3QpOyB9CiAgICBzb3J0KGFsbCh4cykpOwogICAgeHMuZXJhc2UodW5pcXVlKGFsbCh4cykpLCB4cy5lbmQoKSk7CgogICAgdmVjdG9yPHZlY3RvcjxTZWdtZW50Pj4gYWRkU2VnKHN6KHhzKSksIHJlbVNlZyhzeih4cykpOwogICAgdmVjdG9yPHZlY3RvcjxwYWlyPHBhaXI8bGQsbGQ+LGludD4+PiBxdWVyaWVzKHN6KHhzKSk7CgogICAgcmVwKGksMCxuKSB7CiAgICAgICAgU2VnbWVudCBzKHBvbHlfcltpXSwgcG9seV9yWyhpKzEpJW5dKTsKICAgICAgICBpbnQgYSA9IGxvd2VyX2lkeF9sZCh4cywgcy54LmZpcnN0KTsKICAgICAgICBpbnQgYiA9IGxvd2VyX2lkeF9sZCh4cywgcy55LmZpcnN0KTsKICAgICAgICBhZGRTZWdbYV0ucHVzaF9iYWNrKHMpOwogICAgICAgIHJlbVNlZ1tiXS5wdXNoX2JhY2socyk7CiAgICB9CiAgICByZXAoaSwwLG0pIGlmIChyZXN1bHRbaV0gPT0gLTEpIHsKICAgICAgICBpbnQgaWQgPSBsb3dlcl9pZHhfbGQoeHMsIHB0c19yW2ldLmZpcnN0KTsKICAgICAgICBxdWVyaWVzW2lkXS5wdXNoX2JhY2soe3B0c19yW2ldLCBpfSk7CiAgICB9CgogICAgVHJlZTxTZWdtZW50PiBhY3RpdmU7CiAgICByZXAoaSwwLHN6KHhzKSkgewogICAgICAgIGZvciAoYXV0byYgcyA6IHJlbVNlZ1tpXSkgYWN0aXZlLmVyYXNlKHMpOwogICAgICAgIGZvciAoYXV0byYgcXAgOiBxdWVyaWVzW2ldKSB7CiAgICAgICAgICAgIFNlZ21lbnQgdG1wKHFwLmZpcnN0LCBxcC5maXJzdCk7CiAgICAgICAgICAgIGludCBrID0gYWN0aXZlLm9yZGVyX29mX2tleSh0bXApOwogICAgICAgICAgICByZXN1bHRbcXAuc2Vjb25kXSA9IChrICUgMiA9PSAxKTsKICAgICAgICB9CiAgICAgICAgZm9yIChhdXRvJiBzIDogYWRkU2VnW2ldKSBhY3RpdmUuaW5zZXJ0KHMpOwogICAgfQoKICAgIHJlcChpLDAsbSkgY291dCA8PCAocmVzdWx0W2ldID8gIllFU1xuIiA6ICJOT1xuIik7CiAgICByZXR1cm4gMDsKfQo=