#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=(a);i<(n);i++)
#define per(i,a,n) for(int i=(n)-1;i>=(a);i--)
#define mp make_pair
#define pb push_back
typedef double db;
const db EPS = 1e-8;
inline int sign(db a) {
return a < -EPS ? -1 : a > EPS;
}
inline int cmp(db a, db b){
return sign(a-b);
}
struct P {
db x, y;
P() {}
P(db _x, db _y) : x(_x), y(_y) {}
P operator+(P p) { return P(x + p.x, y + p.y); }
P operator-(P p) { return P(x - p.x, y - p.y); }
P operator*(db d) { return P(x * d, y * d); }
P operator/(db d) { return P(x / d, y / d); }
bool operator<(P p) const {
int c = cmp(x, p.x);
if (c) return c == -1;
return cmp(y, p.y) == -1;
}
db dot(P p) { return x * p.x + y * p.y; }
db det(P p) { return x * p.y - y * p.x; }
db distTo(P p) { return (*this-p).abs(); }
db alpha() { return atan2(y, x); }
void read() { cin>>x>>y; }
db abs() { return sqrt(abs2());}
db abs2() { return x * x + y * y; }
P rot90() { return P(-y,x);}
P unit() { return *this/abs(); }
int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
};
struct L{ //ps[0] -> ps[1]
P ps[2];
P& operator[](int i) { return ps[i]; }
P dir() { return ps[1] - ps[0]; }
bool include(P p) { return sign((ps[1] - ps[0]).det(p - ps[0])) > 0; }
L push(){ // push eps outward
const double eps = 1e-6;
P delta = (ps[1] - ps[0]).rot90().unit() * eps;
return {ps[0] - delta, ps[1] - delta};
}
};
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))
P isLL(P p1, P p2, P q1, P q2) {
db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
return (p1 * a2 + p2 * a1) / (a1 + a2);
}
P isLL(L l1,L l2){ return isLL(l1[0],l1[1],l2[0],l2[1]); }
bool intersect(db l1,db r1,db l2,db r2){
if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
return !( cmp(r1,l2) == -1 || cmp(r2,l1) == -1 );
}
bool isSS(P p1, P p2, P q1, P q2){
return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
crossOp(p1,p2,q1) * crossOp(p1,p2,q2) <= 0 && crossOp(q1,q2,p1)
* crossOp(q1,q2,p2) <= 0;
}
bool isMiddle(db a, db m, db b) {
return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
bool isMiddle(P a, P m, P b) {
return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}
bool onSeg(P p1, P p2, P q){
return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}
P proj(P p1, P p2, P q) {
P dir = p2 - p1;
return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}
P reflect(P p1, P p2, P q){
return proj(p1,p2,q) * 2 - q;
}
db nearest(P p1,P p2,P q){
P h = proj(p1,p2,q);
if(isMiddle(p1,h,p2))
return q.distTo(h);
return min(p1.distTo(q),p2.distTo(q));
}
db disSS(P p1, P p2, P q1, P q2){
if(isSS(p1,p2,q1,q2)) return 0;
return min(min(nearest(p1,p2,q1),nearest(p1,p2,q2)), min(nearest(q1,q2,p1),nearest(q1,q2,p2)) );
}
db rad(P p1,P p2){
return atan2l(p1.det(p2),p1.dot(p2));
}
db incircle(P p1, P p2, P p3){
db A = p1.distTo(p2);
db B = p2.distTo(p3);
db C = p3.distTo(p1);
return sqrtl(A*B*C/(A+B+C));
}
//polygon
db area(vector<P> ps){
db ret = 0; rep(i,0,ps.size()) ret += ps[i].det(ps[(i+1)%ps.size()]);
return abs(ret/2);
}
int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
int n = ps.size(), ret = 0;
rep(i,0,n){
P u=ps[i],v=ps[(i+1)%n];
if(onSeg(u,v,p)) return 1;
if(cmp(u.y,v.y)<=0) swap(u,v);
if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
ret ^= crossOp(p,u,v) > 0;
}
return ret*2;
}
vector<P> convexHull(vector<P> ps) {
int n = ps.size(); if(n <= 1) return ps;
sort(ps.begin(), ps.end());
vector<P> qs(n * 2); int k = 0;
for (int i = 0; i < n; qs[k++] = ps[i++])
while (k > 1 && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0) --k;
for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--])
while (k > t && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0) --k;
qs.resize(k - 1);
return qs;
}
vector<P> convexHullNonStrict(vector<P> ps) {
//caution: need to unique the Ps first
int n = ps.size(); if(n <= 1) return ps;
sort(ps.begin(), ps.end());
vector<P> qs(n * 2); int k = 0;
for (int i = 0; i < n; qs[k++] = ps[i++])
while (k > 1 && crossOp(qs[k - 2], qs[k - 1], ps[i]) < 0) --k;
for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--])
while (k > t && crossOp(qs[k - 2], qs[k - 1], ps[i]) < 0) --k;
qs.resize(k - 1);
return qs;
}
db convexDiameter(vector<P> ps){
int n = ps.size(); if(n <= 1) return 0;
int is = 0, js = 0; rep(k,1,n) is = ps[k]<ps[is]?k:is, js = ps[js] < ps[k]?k:js;
int i = is, j = js;
db ret = ps[i].distTo(ps[j]);
do{
if((ps[(i+1)%n]-ps[i]).det(ps[(j+1)%n]-ps[j]) >= 0)
(++j)%=n;
else
(++i)%=n;
ret = max(ret,ps[i].distTo(ps[j]));
}while(i!=is || j!=js);
return ret;
}
vector<P> convexCut(const vector<P>&ps, P q1, P q2) {
vector<P> qs;
int n = ps.size();
rep(i,0,n){
P p1 = ps[i], p2 = ps[(i+1)%n];
int d1 = crossOp(q1,q2,p1), d2 = crossOp(q1,q2,p2);
if(d1 >= 0) qs.pb(p1);
if(d1 * d2 < 0) qs.pb(isLL(p1,p2,q1,q2));
}
return qs;
}
//min_dist
db min_dist(vector<P>&ps,int l,int r){
if(r-l<=5){
db ret = 1e100;
rep(i,l,r) rep(j,l,i) ret = min(ret,ps[i].distTo(ps[j]));
return ret;
}
int m = (l+r)>>1;
db ret = min(min_dist(ps,l,m),min_dist(ps,m,r));
vector<P> qs; rep(i,l,r) if(abs(ps[i].x-ps[m].x)<= ret) qs.pb(ps[i]);
sort(qs.begin(), qs.end(),[](P a,P b) -> bool {return a.y<b.y; });
rep(i,1,qs.size()) for(int j=i-1;j>=0&&qs[j].y>=qs[i].y-ret;--j) ret = min(ret,qs[i].distTo(qs[j]));
return ret;
}
int type(P o1,db r1,P o2,db r2){
db d = o1.distTo(o2);
if(cmp(d,r1+r2) == 1) return 4;
if(cmp(d,r1+r2) == 0) return 3;
if(cmp(d,abs(r1-r2)) == 1) return 2;
if(cmp(d,abs(r1-r2)) == 0) return 1;
return 0;
}
vector<P> isCL(P o,db r,P p1,P p2){
db x = (p1-o).dot(p2-p1), y = (p2-p1).abs2(), d = x * x - y * ((p1-o).abs2() - r*r);
if(sign(d) < 0) return {};
d = max(d,0.0); P m = p1 - (p2-p1)*(x/y), dr = (p2-p1)*(sqrt(d)/y);
return {m-dr,m+dr}; //along dir: p1->p2
}
vector<P> isCC(P o1, db r1, P o2, db r2) { //need to check whether two circles are the same
db d = o1.distTo(o2);
if (cmp(d, r1 + r2) == 1) return {};
d = min(d, r1 + r2);
db y = (r1 * r1 + d * d - r2 * r2) / (2 * d), x = sqrt(r1 * r1 - y * y);
P dr = (o2 - o1).unit();
P q1 = o1 + dr * y, q2 = dr.rot90() * x;
return {q1-q2,q1+q2};//along circle 1
}
vector<P> tanCP(P o, db r, P p) {
db x = (p - o).abs2(), d = x - r * r;
if (sign(d) <= 0) return {}; // on circle => no tangent
P q1 = o + (p - o) * (r * r / x);
P q2 = (p - o).rot90() * (r * sqrt(d) / x);
return {q1-q2,q1+q2}; //counter clock-wise
}
vector<L> extanCC(P o1, db r1, P o2, db r2) {
vector<L> ret;
if (cmp(r1, r2) == 0) {
P dr = (o2 - o1).unit().rot90() * r1;
ret.pb({o1 + dr, o2 + dr}), ret.pb({o1 - dr, o2 - dr});
} else {
P p = (o2 * r1 - o1 * r2) / (r1 - r2);
vector<P> ps = tanCP(o1, r1, p), qs = tanCP(o2, r2, p);
rep(i,0,min(ps.size(),qs.size())) ret.pb({ps[i], qs[i]}); //c1 counter-clock wise
}
return ret;
}
vector<L> intanCC(P o1, db r1, P o2, db r2) {
vector<L> ret;
P p = (o1 * r2 + o2 * r1) / (r1 + r2);
vector<P> ps = tanCP(o1,r1,p), qs = tanCP(o2,r2,p);
rep(i,0,min(ps.size(),qs.size())) ret.pb({ps[i], qs[i]}); //c1 counter-clock wise
return ret;
}
db areaCT(db r, P p1, P p2){
vector<P> is = isCL(P(0,0),r,p1,p2);
if(is.empty()) return r*r*rad(p1,p2)/2;
bool b1 = cmp(p1.abs2(),r*r) == 1, b2 = cmp(p2.abs2(), r*r) == 1;
if(b1 && b2){
if(sign((p1-is[0]).dot(p2-is[0])) <= 0 &&
sign((p1-is[0]).dot(p2-is[0])) <= 0)
return r*r*(rad(p1,is[0]) + rad(is[1],p2))/2 + is[0].det(is[1])/2;
else return r*r*rad(p1,p2)/2;
}
if(b1) return (r*r*rad(p1,is[0]) + is[0].det(p2))/2;
if(b2) return (p1.det(is[1]) + r*r*rad(is[1],p2))/2;
return p1.det(p2)/2;
}
bool parallel(L l0, L l1) { return sign( l0.dir().det( l1.dir() ) ) == 0; }
bool sameDir(L l0, L l1) { return parallel(l0, l1) && sign(l0.dir().dot(l1.dir()) ) == 1; }
bool cmp (P a, P b) {
if (a.quad() != b.quad()) {
return a.quad() < b.quad();
} else {
return sign( a.det(b) ) > 0;
}
}
bool operator < (L l0, L l1) {
if (sameDir(l0, l1)) {
return l1.include(l0[0]);
} else {
return cmp( l0.dir(), l1.dir() );
}
}
bool check(L u, L v, L w) {
return w.include(isLL(u,v));
}
vector<P> halfPlaneIS(vector<L> &l) {
sort(l.begin(), l.end());
deque<L> q;
for (int i = 0; i < (int)l.size(); ++i) {
if (i && sameDir(l[i], l[i - 1])) continue;
while (q.size() > 1 && !check(q[q.size() - 2], q[q.size() - 1], l[i])) q.pop_back();
while (q.size() > 1 && !check(q[1], q[0], l[i])) q.pop_front();
q.push_back(l[i]);
}
while (q.size() > 2 && !check(q[q.size() - 2], q[q.size() - 1], q[0])) q.pop_back();
while (q.size() > 2 && !check(q[1], q[0], q[q.size() - 1])) q.pop_front();
vector<P> ret;
for (int i = 0; i < (int)q.size(); ++i) ret.push_back(isLL(q[i], q[(i + 1) % q.size()]));
return ret;
}
int main(){
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiNkZWZpbmUgcmVwKGksYSxuKSBmb3IoaW50IGk9KGEpO2k8KG4pO2krKykKI2RlZmluZSBwZXIoaSxhLG4pIGZvcihpbnQgaT0obiktMTtpPj0oYSk7aS0tKQojZGVmaW5lIG1wIG1ha2VfcGFpcgojZGVmaW5lIHBiIHB1c2hfYmFjawoKdHlwZWRlZiBkb3VibGUgZGI7Cgpjb25zdCBkYiBFUFMgPSAxZS04OwoKaW5saW5lIGludCBzaWduKGRiIGEpIHsKCXJldHVybiBhIDwgLUVQUyA/IC0xIDogYSA+IEVQUzsKfQoKaW5saW5lIGludCBjbXAoZGIgYSwgZGIgYil7CglyZXR1cm4gc2lnbihhLWIpOwp9CgpzdHJ1Y3QgUCB7CglkYiB4LCB5OwoJUCgpIHt9CglQKGRiIF94LCBkYiBfeSkgOiB4KF94KSwgeShfeSkge30KCVAgb3BlcmF0b3IrKFAgcCkgeyByZXR1cm4gUCh4ICsgcC54LCB5ICsgcC55KTsgfQoJUCBvcGVyYXRvci0oUCBwKSB7IHJldHVybiBQKHggLSBwLngsIHkgLSBwLnkpOyB9CglQIG9wZXJhdG9yKihkYiBkKSB7IHJldHVybiBQKHggKiBkLCB5ICogZCk7IH0KCVAgb3BlcmF0b3IvKGRiIGQpIHsgcmV0dXJuIFAoeCAvIGQsIHkgLyBkKTsgfQoJYm9vbCBvcGVyYXRvcjwoUCBwKSBjb25zdCB7IAoJCWludCBjID0gY21wKHgsIHAueCk7CgkJaWYgKGMpIHJldHVybiBjID09IC0xOwoJCXJldHVybiBjbXAoeSwgcC55KSA9PSAtMTsKCX0KCWRiIGRvdChQIHApIHsgcmV0dXJuIHggKiBwLnggKyB5ICogcC55OyB9CglkYiBkZXQoUCBwKSB7IHJldHVybiB4ICogcC55IC0geSAqIHAueDsgfQoJZGIgZGlzdFRvKFAgcCkgeyByZXR1cm4gKCp0aGlzLXApLmFicygpOyB9CglkYiBhbHBoYSgpIHsgcmV0dXJuIGF0YW4yKHksIHgpOyB9Cgl2b2lkIHJlYWQoKSB7IGNpbj4+eD4+eTsgfQoJZGIgYWJzKCkgeyByZXR1cm4gc3FydChhYnMyKCkpO30KCWRiIGFiczIoKSB7IHJldHVybiB4ICogeCArIHkgKiB5OyB9CglQIHJvdDkwKCkgeyByZXR1cm4gUCgteSx4KTt9CglQIHVuaXQoKSB7IHJldHVybiAqdGhpcy9hYnMoKTsgfQogICAgaW50IHF1YWQoKSBjb25zdCB7IHJldHVybiBzaWduKHkpID09IDEgfHwgKHNpZ24oeSkgPT0gMCAmJiBzaWduKHgpID49IDApOyB9Cn07CgpzdHJ1Y3QgTHsgLy9wc1swXSAtPiBwc1sxXQoJUCBwc1syXTsKCVAmIG9wZXJhdG9yW10oaW50IGkpIHsgcmV0dXJuIHBzW2ldOyB9CglQIGRpcigpIHsgcmV0dXJuIHBzWzFdIC0gcHNbMF07IH0KIAlib29sIGluY2x1ZGUoUCBwKSB7IHJldHVybiBzaWduKChwc1sxXSAtIHBzWzBdKS5kZXQocCAtIHBzWzBdKSkgPiAwOyB9CiAJTCBwdXNoKCl7IC8vIHB1c2ggZXBzIG91dHdhcmQKIAkJY29uc3QgZG91YmxlIGVwcyA9IDFlLTY7CiAJCVAgZGVsdGEgPSAocHNbMV0gLSBwc1swXSkucm90OTAoKS51bml0KCkgKiBlcHM7CiAJCXJldHVybiB7cHNbMF0gLSBkZWx0YSwgcHNbMV0gLSBkZWx0YX07CiAJfQp9OwoKI2RlZmluZSBjcm9zcyhwMSxwMixwMykgKChwMi54LXAxLngpKihwMy55LXAxLnkpLShwMy54LXAxLngpKihwMi55LXAxLnkpKQojZGVmaW5lIGNyb3NzT3AocDEscDIscDMpIHNpZ24oY3Jvc3MocDEscDIscDMpKQoKUCBpc0xMKFAgcDEsIFAgcDIsIFAgcTEsIFAgcTIpIHsKCWRiIGExID0gY3Jvc3MocTEsIHEyLCBwMSksIGEyID0gLWNyb3NzKHExLCBxMiwgcDIpOwoJcmV0dXJuIChwMSAqIGEyICsgcDIgKiBhMSkgLyAoYTEgKyBhMik7Cn0KClAgaXNMTChMIGwxLEwgbDIpeyByZXR1cm4gaXNMTChsMVswXSxsMVsxXSxsMlswXSxsMlsxXSk7IH0KCmJvb2wgaW50ZXJzZWN0KGRiIGwxLGRiIHIxLGRiIGwyLGRiIHIyKXsKCWlmKGwxPnIxKSBzd2FwKGwxLHIxKTsgaWYobDI+cjIpIHN3YXAobDIscjIpOyAKCXJldHVybiAhKCBjbXAocjEsbDIpID09IC0xIHx8IGNtcChyMixsMSkgPT0gLTEgKTsKfQoKYm9vbCBpc1NTKFAgcDEsIFAgcDIsIFAgcTEsIFAgcTIpewogICAgcmV0dXJuIGludGVyc2VjdChwMS54LHAyLngscTEueCxxMi54KSAmJiBpbnRlcnNlY3QocDEueSxwMi55LHExLnkscTIueSkgJiYgCiAgICBjcm9zc09wKHAxLHAyLHExKSAqIGNyb3NzT3AocDEscDIscTIpIDw9IDAgJiYgY3Jvc3NPcChxMSxxMixwMSkKICAgICAgICAgICAgKiBjcm9zc09wKHExLHEyLHAyKSA8PSAwOwp9Cgpib29sIGlzTWlkZGxlKGRiIGEsIGRiIG0sIGRiIGIpIHsKICAgIHJldHVybiBzaWduKGEgLSBtKSA9PSAwIHx8IHNpZ24oYiAtIG0pID09IDAgfHwgKGEgPCBtICE9IGIgPCBtKTsKfQogCmJvb2wgaXNNaWRkbGUoUCBhLCBQIG0sIFAgYikgewogICAgcmV0dXJuIGlzTWlkZGxlKGEueCwgbS54LCBiLngpICYmIGlzTWlkZGxlKGEueSwgbS55LCBiLnkpOwp9Cgpib29sIG9uU2VnKFAgcDEsIFAgcDIsIFAgcSl7CglyZXR1cm4gY3Jvc3NPcChwMSxwMixxKSA9PSAwICYmIGlzTWlkZGxlKHAxLCBxLCBwMik7Cn0KClAgcHJvaihQIHAxLCBQIHAyLCBQIHEpIHsKICAgIFAgZGlyID0gcDIgLSBwMTsKICAgIHJldHVybiBwMSArIGRpciAqIChkaXIuZG90KHEgLSBwMSkgLyBkaXIuYWJzMigpKTsKfQoKUCByZWZsZWN0KFAgcDEsIFAgcDIsIFAgcSl7CglyZXR1cm4gcHJvaihwMSxwMixxKSAqIDIgLSBxOwp9CgpkYiBuZWFyZXN0KFAgcDEsUCBwMixQIHEpewoJUCBoID0gcHJvaihwMSxwMixxKTsKCWlmKGlzTWlkZGxlKHAxLGgscDIpKQoJCXJldHVybiBxLmRpc3RUbyhoKTsKCXJldHVybiBtaW4ocDEuZGlzdFRvKHEpLHAyLmRpc3RUbyhxKSk7Cn0KCmRiIGRpc1NTKFAgcDEsIFAgcDIsIFAgcTEsIFAgcTIpewoJaWYoaXNTUyhwMSxwMixxMSxxMikpIHJldHVybiAwOwoJcmV0dXJuIG1pbihtaW4obmVhcmVzdChwMSxwMixxMSksbmVhcmVzdChwMSxwMixxMikpLCBtaW4obmVhcmVzdChxMSxxMixwMSksbmVhcmVzdChxMSxxMixwMikpICk7Cn0KCmRiIHJhZChQIHAxLFAgcDIpewoJcmV0dXJuIGF0YW4ybChwMS5kZXQocDIpLHAxLmRvdChwMikpOwp9CgpkYiBpbmNpcmNsZShQIHAxLCBQIHAyLCBQIHAzKXsKCWRiIEEgPSBwMS5kaXN0VG8ocDIpOwoJZGIgQiA9IHAyLmRpc3RUbyhwMyk7CglkYiBDID0gcDMuZGlzdFRvKHAxKTsKCXJldHVybiBzcXJ0bChBKkIqQy8oQStCK0MpKTsKfQoKLy9wb2x5Z29uCgpkYiBhcmVhKHZlY3RvcjxQPiBwcyl7CglkYiByZXQgPSAwOyByZXAoaSwwLHBzLnNpemUoKSkgcmV0ICs9IHBzW2ldLmRldChwc1soaSsxKSVwcy5zaXplKCldKTsgCglyZXR1cm4gYWJzKHJldC8yKTsKfQoKaW50IGNvbnRhaW4odmVjdG9yPFA+IHBzLCBQIHApeyAvLzI6aW5zaWRlLDE6b25fc2VnLDA6b3V0c2lkZQoJaW50IG4gPSBwcy5zaXplKCksIHJldCA9IDA7CQoJcmVwKGksMCxuKXsKCQlQIHU9cHNbaV0sdj1wc1soaSsxKSVuXTsKCQlpZihvblNlZyh1LHYscCkpIHJldHVybiAxOwoJCWlmKGNtcCh1Lnksdi55KTw9MCkgc3dhcCh1LHYpOwoJCWlmKGNtcChwLnksdS55KSA+MCB8fCBjbXAocC55LHYueSkgPD0gMCkgY29udGludWU7CgkJcmV0IF49IGNyb3NzT3AocCx1LHYpID4gMDsKCX0KCXJldHVybiByZXQqMjsKfQoKdmVjdG9yPFA+IGNvbnZleEh1bGwodmVjdG9yPFA+IHBzKSB7CiAgICBpbnQgbiA9IHBzLnNpemUoKTsgaWYobiA8PSAxKSByZXR1cm4gcHM7CiAgICBzb3J0KHBzLmJlZ2luKCksIHBzLmVuZCgpKTsKICAgIHZlY3RvcjxQPiBxcyhuICogMik7IGludCBrID0gMDsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgcXNbaysrXSA9IHBzW2krK10pIAogICAgICAgIHdoaWxlIChrID4gMSAmJiBjcm9zc09wKHFzW2sgLSAyXSwgcXNbayAtIDFdLCBwc1tpXSkgPD0gMCkgLS1rOwogICAgZm9yIChpbnQgaSA9IG4gLSAyLCB0ID0gazsgaSA+PSAwOyBxc1trKytdID0gcHNbaS0tXSkKICAgICAgIAl3aGlsZSAoayA+IHQgJiYgY3Jvc3NPcChxc1trIC0gMl0sIHFzW2sgLSAxXSwgcHNbaV0pIDw9IDApIC0tazsKICAgIHFzLnJlc2l6ZShrIC0gMSk7CiAgICByZXR1cm4gcXM7Cn0KCnZlY3RvcjxQPiBjb252ZXhIdWxsTm9uU3RyaWN0KHZlY3RvcjxQPiBwcykgewoJLy9jYXV0aW9uOiBuZWVkIHRvIHVuaXF1ZSB0aGUgUHMgZmlyc3QKICAgIGludCBuID0gcHMuc2l6ZSgpOyBpZihuIDw9IDEpIHJldHVybiBwczsKICAgIHNvcnQocHMuYmVnaW4oKSwgcHMuZW5kKCkpOwogICAgdmVjdG9yPFA+IHFzKG4gKiAyKTsgaW50IGsgPSAwOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBxc1trKytdID0gcHNbaSsrXSkgCiAgICAgICAgd2hpbGUgKGsgPiAxICYmIGNyb3NzT3AocXNbayAtIDJdLCBxc1trIC0gMV0sIHBzW2ldKSA8IDApIC0tazsKICAgIGZvciAoaW50IGkgPSBuIC0gMiwgdCA9IGs7IGkgPj0gMDsgcXNbaysrXSA9IHBzW2ktLV0pCiAgICAgICAJd2hpbGUgKGsgPiB0ICYmIGNyb3NzT3AocXNbayAtIDJdLCBxc1trIC0gMV0sIHBzW2ldKSA8IDApIC0tazsKICAgIHFzLnJlc2l6ZShrIC0gMSk7CiAgICByZXR1cm4gcXM7Cn0KCmRiIGNvbnZleERpYW1ldGVyKHZlY3RvcjxQPiBwcyl7CglpbnQgbiA9IHBzLnNpemUoKTsgaWYobiA8PSAxKSByZXR1cm4gMDsKCWludCBpcyA9IDAsIGpzID0gMDsgcmVwKGssMSxuKSBpcyA9IHBzW2tdPHBzW2lzXT9rOmlzLCBqcyA9IHBzW2pzXSA8IHBzW2tdP2s6anM7CglpbnQgaSA9IGlzLCBqID0ganM7CglkYiByZXQgPSBwc1tpXS5kaXN0VG8ocHNbal0pOwoJZG97CgkJaWYoKHBzWyhpKzEpJW5dLXBzW2ldKS5kZXQocHNbKGorMSklbl0tcHNbal0pID49IDApCgkJCSgrK2opJT1uOwoJCWVsc2UKCQkJKCsraSklPW47CgkJcmV0ID0gbWF4KHJldCxwc1tpXS5kaXN0VG8ocHNbal0pKTsKCX13aGlsZShpIT1pcyB8fCBqIT1qcyk7CglyZXR1cm4gcmV0Owp9Cgp2ZWN0b3I8UD4gY29udmV4Q3V0KGNvbnN0IHZlY3RvcjxQPiZwcywgUCBxMSwgUCBxMikgewoJdmVjdG9yPFA+IHFzOwoJaW50IG4gPSBwcy5zaXplKCk7CglyZXAoaSwwLG4pewoJCVAgcDEgPSBwc1tpXSwgcDIgPSBwc1soaSsxKSVuXTsKCQlpbnQgZDEgPSBjcm9zc09wKHExLHEyLHAxKSwgZDIgPSBjcm9zc09wKHExLHEyLHAyKTsKCQlpZihkMSA+PSAwKSBxcy5wYihwMSk7CgkJaWYoZDEgKiBkMiA8IDApIHFzLnBiKGlzTEwocDEscDIscTEscTIpKTsKCX0KCXJldHVybiBxczsKfQoKLy9taW5fZGlzdAoKZGIgbWluX2Rpc3QodmVjdG9yPFA+JnBzLGludCBsLGludCByKXsKCWlmKHItbDw9NSl7CgkJZGIgcmV0ID0gMWUxMDA7CgkJcmVwKGksbCxyKSByZXAoaixsLGkpIHJldCA9IG1pbihyZXQscHNbaV0uZGlzdFRvKHBzW2pdKSk7CgkJcmV0dXJuIHJldDsKCX0KCWludCBtID0gKGwrcik+PjE7CglkYiByZXQgPSBtaW4obWluX2Rpc3QocHMsbCxtKSxtaW5fZGlzdChwcyxtLHIpKTsKCXZlY3RvcjxQPiBxczsgcmVwKGksbCxyKSBpZihhYnMocHNbaV0ueC1wc1ttXS54KTw9IHJldCkgcXMucGIocHNbaV0pOwoJc29ydChxcy5iZWdpbigpLCBxcy5lbmQoKSxbXShQIGEsUCBiKSAtPiBib29sIHtyZXR1cm4gYS55PGIueTsgfSk7CglyZXAoaSwxLHFzLnNpemUoKSkgZm9yKGludCBqPWktMTtqPj0wJiZxc1tqXS55Pj1xc1tpXS55LXJldDstLWopIHJldCA9IG1pbihyZXQscXNbaV0uZGlzdFRvKHFzW2pdKSk7CglyZXR1cm4gcmV0Owp9CgppbnQgdHlwZShQIG8xLGRiIHIxLFAgbzIsZGIgcjIpewoJZGIgZCA9IG8xLmRpc3RUbyhvMik7CglpZihjbXAoZCxyMStyMikgPT0gMSkgcmV0dXJuIDQ7CglpZihjbXAoZCxyMStyMikgPT0gMCkgcmV0dXJuIDM7CglpZihjbXAoZCxhYnMocjEtcjIpKSA9PSAxKSByZXR1cm4gMjsKCWlmKGNtcChkLGFicyhyMS1yMikpID09IDApIHJldHVybiAxOwoJcmV0dXJuIDA7Cn0KCnZlY3RvcjxQPiBpc0NMKFAgbyxkYiByLFAgcDEsUCBwMil7CglkYiB4ID0gKHAxLW8pLmRvdChwMi1wMSksIHkgPSAocDItcDEpLmFiczIoKSwgZCA9IHggKiB4IC0geSAqICgocDEtbykuYWJzMigpIC0gcipyKTsKCWlmKHNpZ24oZCkgPCAwKSByZXR1cm4ge307CglkID0gbWF4KGQsMC4wKTsgUCBtID0gcDEgLSAocDItcDEpKih4L3kpLCBkciA9IChwMi1wMSkqKHNxcnQoZCkveSk7CglyZXR1cm4ge20tZHIsbStkcn07IC8vYWxvbmcgZGlyOiBwMS0+cDIKfQoKdmVjdG9yPFA+IGlzQ0MoUCBvMSwgZGIgcjEsIFAgbzIsIGRiIHIyKSB7IC8vbmVlZCB0byBjaGVjayB3aGV0aGVyIHR3byBjaXJjbGVzIGFyZSB0aGUgc2FtZQoJZGIgZCA9IG8xLmRpc3RUbyhvMik7IAoJaWYgKGNtcChkLCByMSArIHIyKSA9PSAxKSByZXR1cm4ge307CglkID0gbWluKGQsIHIxICsgcjIpOwoJZGIgeSA9IChyMSAqIHIxICsgZCAqIGQgLSByMiAqIHIyKSAvICgyICogZCksIHggPSBzcXJ0KHIxICogcjEgLSB5ICogeSk7CglQIGRyID0gKG8yIC0gbzEpLnVuaXQoKTsKCVAgcTEgPSBvMSArIGRyICogeSwgcTIgPSBkci5yb3Q5MCgpICogeDsKCXJldHVybiB7cTEtcTIscTErcTJ9Oy8vYWxvbmcgY2lyY2xlIDEKfQoKdmVjdG9yPFA+IHRhbkNQKFAgbywgZGIgciwgUCBwKSB7CglkYiB4ID0gKHAgLSBvKS5hYnMyKCksIGQgPSB4IC0gciAqIHI7CglpZiAoc2lnbihkKSA8PSAwKSByZXR1cm4ge307IC8vIG9uIGNpcmNsZSA9PiBubyB0YW5nZW50CglQIHExID0gbyArIChwIC0gbykgKiAociAqIHIgLyB4KTsKCVAgcTIgPSAocCAtIG8pLnJvdDkwKCkgKiAociAqIHNxcnQoZCkgLyB4KTsKCXJldHVybiB7cTEtcTIscTErcTJ9OyAvL2NvdW50ZXIgY2xvY2std2lzZQp9CgoKdmVjdG9yPEw+IGV4dGFuQ0MoUCBvMSwgZGIgcjEsIFAgbzIsIGRiIHIyKSB7Cgl2ZWN0b3I8TD4gcmV0OwoJaWYgKGNtcChyMSwgcjIpID09IDApIHsKCQlQIGRyID0gKG8yIC0gbzEpLnVuaXQoKS5yb3Q5MCgpICogcjE7CgkJcmV0LnBiKHtvMSArIGRyLCBvMiArIGRyfSksIHJldC5wYih7bzEgLSBkciwgbzIgLSBkcn0pOwoJfSBlbHNlIHsKCQlQIHAgPSAobzIgKiByMSAtIG8xICogcjIpIC8gKHIxIC0gcjIpOwoJCXZlY3RvcjxQPiBwcyA9IHRhbkNQKG8xLCByMSwgcCksIHFzID0gdGFuQ1AobzIsIHIyLCBwKTsKCQlyZXAoaSwwLG1pbihwcy5zaXplKCkscXMuc2l6ZSgpKSkgcmV0LnBiKHtwc1tpXSwgcXNbaV19KTsgLy9jMSBjb3VudGVyLWNsb2NrIHdpc2UKCX0KCXJldHVybiByZXQ7Cn0KCnZlY3RvcjxMPiBpbnRhbkNDKFAgbzEsIGRiIHIxLCBQIG8yLCBkYiByMikgewoJdmVjdG9yPEw+IHJldDsKIAlQIHAgPSAobzEgKiByMiArIG8yICogcjEpIC8gKHIxICsgcjIpOwogCXZlY3RvcjxQPiBwcyA9IHRhbkNQKG8xLHIxLHApLCBxcyA9IHRhbkNQKG8yLHIyLHApOwoJcmVwKGksMCxtaW4ocHMuc2l6ZSgpLHFzLnNpemUoKSkpIHJldC5wYih7cHNbaV0sIHFzW2ldfSk7IC8vYzEgY291bnRlci1jbG9jayB3aXNlCglyZXR1cm4gcmV0Owp9CgpkYiBhcmVhQ1QoZGIgciwgUCBwMSwgUCBwMil7Cgl2ZWN0b3I8UD4gaXMgPSBpc0NMKFAoMCwwKSxyLHAxLHAyKTsKCWlmKGlzLmVtcHR5KCkpIHJldHVybiByKnIqcmFkKHAxLHAyKS8yOwoJYm9vbCBiMSA9IGNtcChwMS5hYnMyKCkscipyKSA9PSAxLCBiMiA9IGNtcChwMi5hYnMyKCksIHIqcikgPT0gMTsKCWlmKGIxICYmIGIyKXsKCQlpZihzaWduKChwMS1pc1swXSkuZG90KHAyLWlzWzBdKSkgPD0gMCAmJgoJCQlzaWduKChwMS1pc1swXSkuZG90KHAyLWlzWzBdKSkgPD0gMCkKCQlyZXR1cm4gcipyKihyYWQocDEsaXNbMF0pICsgcmFkKGlzWzFdLHAyKSkvMiArIGlzWzBdLmRldChpc1sxXSkvMjsKCQllbHNlIHJldHVybiByKnIqcmFkKHAxLHAyKS8yOwoJfQoJaWYoYjEpIHJldHVybiAocipyKnJhZChwMSxpc1swXSkgKyBpc1swXS5kZXQocDIpKS8yOwoJaWYoYjIpIHJldHVybiAocDEuZGV0KGlzWzFdKSArIHIqcipyYWQoaXNbMV0scDIpKS8yOwoJcmV0dXJuIHAxLmRldChwMikvMjsKfQoKYm9vbCBwYXJhbGxlbChMIGwwLCBMIGwxKSB7IHJldHVybiBzaWduKCBsMC5kaXIoKS5kZXQoIGwxLmRpcigpICkgKSA9PSAwOyB9Cgpib29sIHNhbWVEaXIoTCBsMCwgTCBsMSkgeyByZXR1cm4gcGFyYWxsZWwobDAsIGwxKSAmJiBzaWduKGwwLmRpcigpLmRvdChsMS5kaXIoKSkgKSA9PSAxOyB9Cgpib29sIGNtcCAoUCBhLCAgUCBiKSB7CglpZiAoYS5xdWFkKCkgIT0gYi5xdWFkKCkpIHsKCQlyZXR1cm4gYS5xdWFkKCkgPCBiLnF1YWQoKTsKCX0gZWxzZSB7CgkJcmV0dXJuIHNpZ24oIGEuZGV0KGIpICkgPiAwOwoJfQp9Cgpib29sIG9wZXJhdG9yIDwgKEwgbDAsIEwgbDEpIHsKCWlmIChzYW1lRGlyKGwwLCBsMSkpIHsKCQlyZXR1cm4gbDEuaW5jbHVkZShsMFswXSk7Cgl9IGVsc2UgewoJCXJldHVybiBjbXAoIGwwLmRpcigpLCBsMS5kaXIoKSApOwoJfQp9Cgpib29sIGNoZWNrKEwgdSwgTCB2LCBMIHcpIHsgCglyZXR1cm4gdy5pbmNsdWRlKGlzTEwodSx2KSk7IAp9Cgp2ZWN0b3I8UD4gaGFsZlBsYW5lSVModmVjdG9yPEw+ICZsKSB7Cglzb3J0KGwuYmVnaW4oKSwgbC5lbmQoKSk7CglkZXF1ZTxMPiBxOwoJZm9yIChpbnQgaSA9IDA7IGkgPCAoaW50KWwuc2l6ZSgpOyArK2kpIHsKIAkJaWYgKGkgJiYgc2FtZURpcihsW2ldLCBsW2kgLSAxXSkpIGNvbnRpbnVlOwogCQl3aGlsZSAocS5zaXplKCkgPiAxICYmICFjaGVjayhxW3Euc2l6ZSgpIC0gMl0sIHFbcS5zaXplKCkgLSAxXSwgbFtpXSkpIHEucG9wX2JhY2soKTsKIAkJd2hpbGUgKHEuc2l6ZSgpID4gMSAmJiAhY2hlY2socVsxXSwgcVswXSwgbFtpXSkpIHEucG9wX2Zyb250KCk7CiAJCXEucHVzaF9iYWNrKGxbaV0pOwogCX0KCXdoaWxlIChxLnNpemUoKSA+IDIgJiYgIWNoZWNrKHFbcS5zaXplKCkgLSAyXSwgcVtxLnNpemUoKSAtIDFdLCBxWzBdKSkgcS5wb3BfYmFjaygpOwoJd2hpbGUgKHEuc2l6ZSgpID4gMiAmJiAhY2hlY2socVsxXSwgcVswXSwgcVtxLnNpemUoKSAtIDFdKSkgcS5wb3BfZnJvbnQoKTsKCXZlY3RvcjxQPiByZXQ7Cglmb3IgKGludCBpID0gMDsgaSA8IChpbnQpcS5zaXplKCk7ICsraSkgcmV0LnB1c2hfYmFjayhpc0xMKHFbaV0sIHFbKGkgKyAxKSAlIHEuc2l6ZSgpXSkpOwoJcmV0dXJuIHJldDsKfQoKaW50IG1haW4oKXsKCXJldHVybiAwOwp9