Problem:
牽牛と織女
織女は天帝の子供でしたが、父の言いつけであけてもくれても機を織っていました。
織女の織る雲錦という見事な布で仕立てた服を着るのが天帝の楽しみでした。雲錦は寿命が短くすぐに劣化してしまいますが、働き者の織女が毎日織ってくれるので、問題はありませんでした。織女は、父の言いつけを守り、毎日毎日雲錦を織り続けていたので、ボーイフレンドはいませんでした。かわいそうに思った父は、天の川の向こう岸に住む牽牛という働き者を紹介し、嫁入りさせました。
すると、織女は、結婚の楽しさに夢中になって、機織りなどそっちのけで、牽牛と遊び呆けています。天帝のお気に入りの雲錦の服も新しく仕立てられないためボロボロになってしまいました。
これには父も怒って、織女を宮殿に連れ戻したいと思いました。しかし人間である牽牛の前にボロボロの服で姿を現すわけにはいきません。遊び呆けている二人を 3 角形の壁で遮断し自分以外の全てのものが行き来できなくすることを考えました。そして、牽牛に見つからずに、織女に会って、まじめに機を織るか、さもなければ強制的に連れ帰ると宣言するというのです。
天帝はこの作戦を遂行するために 3 角形の壁生成装置を開発することにしました。3 角形の 3 頂点の位置
(xp
1
, yp
1
)
,
(xp
2
, yp
2
)
,
(xp
3
, yp
3
)
、牽牛の位置
(xk, yk)
、および織女の位置
(xs, ys)
、を入力とし、三角形が牽牛と織女を遮断しているか否かを判定し、遮断できている場合は OK、遮断できていない場合には NG を出力するプログラムを作成してください。ただし、遮断しているとは、牽牛と織女のいずれかが三角形の内側にあり、他方が外側にある場合を言います。牽牛と織女は三角形の頂点もしくは辺の上にはいないものとします。
織女と牽牛は時々刻々場所を変えるため、プログラムは様々な位置情報を入力し質問に答えなければなりません。
Input
入力は以下の形式で与えられます。
n
query
1
query
2
:
query
n
１行目に判別したい情報の個数
n
(
n
≤ 10000)、続く
n
行に
i
番目の質問
query
i
が与えられます。各質問は以下の形式で与えられます。
xp
1
yp
1
xp
2
yp
2
xp
3
yp
3
xk
yk
xs
ys
各質問として、3 角形の 3 頂点の位置、牽牛の位置、および織女の位置 (-1000 ≤
xp
1
,
yp
1
,
xp
2
,
yp
2
,
xp
3
,
yp
3
,
xk
,
yk
,
xs
,
ys
≤ 1000) が１行に与えられます。入力はすべて整数です。
Output
質問ごとに、判定結果 OK または NG を１行に出力してください。
Sample Input
5
2 5 9 2 8 9 2 11 6 5
2 5 9 2 8 9 2 11 12 6
2 5 9 2 8 9 2 11 11 9
14 1 25 7 17 12 17 9 20 5
14 1 25 7 17 12 22 13 20 5
Output for the Sample Input
OK
NG
NG
NG
OK

Submitted solutions:

code_snippet: #include "bits/stdc++.h"

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

/* 幾何の基本 */
#include <complex>

typedef long double ld;
typedef complex<ld> Point;//複素数

const ld eps = 1e-9, pi = acos(-1.0);

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// 点の入力
Point input_point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// 誤差つき等号判定
bool eq(ld a, ld b) {
	return (abs(a - b) < eps);
}

// 内積
ld dot(Point a, Point b) {
	return real(conj(a) * b);//conj::共役複素数
}

// 外積
ld cross(Point a, Point b) {
	return imag(conj(a) * b);
}

// 直線の定義
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
};

/*int main(){
Point a(1,1),b(2,2);
Line l(a,b);
}*/

// 円の定義
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// CCW::counter clockwise
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps) return 1;   // a,b,cが反時計周りの順に並ぶ
	if (cross(b, c) < -eps) return -1; // a,b,cが時計周りの順に並ぶ
	if (dot(b, c) < 0) return 2;       // c,a,bの順に直線に並ぶ
	if (norm(b) < norm(c)) return -2;  // a,b,cの順に直線に並ぶ
	return 0;                          // a,c,bの順に直線に並ぶ
}


/* 交差判定 */

// 直線と直線の交差判定
//l::直線　s::線分
bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// 直線と線分の交差判定 *slide誤植
bool isis_ls(Line l, Line s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// 線分と線分の交差判定
bool isis_ss(Line s, Line t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// 点の直線上判定
bool isis_lp(Line l, Point p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// 点の線分上判定
bool isis_sp(Line s, Point p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// 垂線の足
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	//norm::絶対値の2乗
	return l.a + t * (l.a - l.b);
}

// 直線と直線の交点
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

// 直線と点の距離
ld dist_lp(Line l, Point p) {
	return abs(p - proj(l, p));
}

// 直線と直線の距離
ld dist_ll(Line l, Line m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// 直線と線分の距離
ld dist_ls(Line l, Line s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// 線分と点の距離
ld dist_sp(Line s, Point p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// 線分と線分の距離
ld dist_ss(Line s, Line t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


/* 円 */

// 円と円の交点
vector<Point> is_cc(Circle c1, Circle c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

// 円と直線の交点
vector<Point> is_lc(Circle c, Line l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// 円と線分の距離
vector<Point> is_sc(Circle c, Line l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// 円と点の接線
vector<Line> tangent_cp(Circle c, Point p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// 円と円の接線
vector<Line> tangent_cc(Circle c1, Circle c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), ALL(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}


/* 多角形 */

typedef vector<Point> Polygon;

// 面積
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	REP(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

// 多角形の回転方向
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// 円の内外判定
// -1 => out
//  0 => on
//  1 => in
int is_in_polygon(const Polygon &poly, Point p) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}

// 凸包
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}

// 凸カット
Polygon convex_cut(const Polygon &ps, Line l) {
	int n = ps.size();
	Polygon Q;
	REP(i, n) {
		Point A = ps[i], B = ps[(i + 1) % n];
		Line m = Line(A, B);
		if (ccw(l.a, l.b, A) != -1) Q.push_back(A);
		if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0 && isis_ll(l, m))
			Q.push_back(is_ll(l, m));
	}
	return Q;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

    int n;cin>>n;
    for(int i=0;i<n;i++){
        ld xp1,yp1,xp2,yp2,xp3,yp3,xk,yk,xs,ys;
        //Tringle:(xp1,yp1)-(xp2,yp2)-(xp3,yp3) Altair:(xk,yk) Vega:(xs,ys)
        cin>>xp1>>yp1>>xp2>>yp2>>xp3>>yp3>>xk>>yk>>xs>>ys;
        Point alt=Point(xk,yk),veg=Point(xs,ys);
        vector<Point> tri;
        tri.push_back(Point(xp1,yp1));tri.push_back(Point(xp2,yp2));tri.push_back(Point(xp3,yp3));
        Polygon sankaku=Polygon(tri);
        //cout<<is_in_polygon(sankaku,alt)<<" "<<is_in_polygon(sankaku,veg)<<endl;
        if(is_in_polygon(sankaku,alt)!=is_in_polygon(sankaku,veg)) cout<<"OK"<<endl;
        else cout<<"NG"<<endl;
    }    
}
accuracy: 1
time_ms: 20
memory_kb: 3516
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

double area(double x1, double y1, double x2, double y2, double x3, double y3) {
    return abs((x1 * (y2 - y3) + x2 * (y3 - y1)) + x3 * (y1 - y2)) / 2.0;
}

double xp1, yp1, xp2, yp2, xp3, yp3, xk, yk, xs, ys;

bool inTriangle(double x, double y) {
    double totalArea = area(xp1, yp1, xp2, yp2, xp3, yp3);

    double areaPBC = area(x, y, xp2, yp2, xp3, yp3);
    double areaPCA = area(x, y, xp1, yp1, xp3, yp3);
    double areaPAB = area(x, y, xp1, yp1, xp2, yp2);

    double sumOfTriangles = areaPAB + areaPCA + areaPBC;

    return (abs(totalArea - sumOfTriangles) < 1e-6);
}

int main() {
    int t; cin >> t;
    while (t--) {
        cin >> xp1 >> yp1 >> xp2 >> yp2 >> xp3 >> yp3 >> xk >> yk >> xs >> ys;
        if (inTriangle(xk, yk) == inTriangle(xs, ys))
            cout << "NG" << endl;
        else
            cout << "OK" << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3096
final_rank: 8

code_snippet: #include <bits/stdc++.h>

#include <algorithm>
#include <cmath>
#include <iostream>
#include <iterator>
#include <utility>
#include <vector>

using Real = long double;
constexpr Real EPS = 1e-10;
const Real PI = std::acos(-1);

int sign(Real x) {
    return x < -EPS ? -1 : x > EPS ? 1 : 0;
}

bool eq(Real lhs, Real rhs) {
    return sign(rhs - lhs) == 0;
}

bool lte(Real lhs, Real rhs) {
    return sign(rhs - lhs) >= 0;
}

bool lt(Real lhs, Real rhs) {
    return sign(rhs - lhs) > 0;
}

bool gte(Real lhs, Real rhs) {
    return lte(rhs, lhs);
}

bool gt(Real lhs, Real rhs) {
    return lt(rhs, lhs);
}

struct Point {
    Real x;
    Real y;
    Point(Real x = 0, Real y = 0): x(x), y(y) {}
    Point& operator+=(Point rhs) {
        this->x += rhs.x;
        this->y += rhs.y;
        return *this;
    }
    Point& operator-=(Point rhs) {
        this->x -= rhs.x;
        this->y -= rhs.y;
        return *this;
    }
    Point& operator*=(Real k) {
        this->x *= k;
        this->y *= k;
        return *this;
    }
    Point& operator/=(Real k) {
        this->x /= k;
        this->y /= k;
        return *this;
    }
    friend Point operator+(Point lhs, Point rhs) {
        return lhs += rhs;
    }
    friend Point operator-(Point lhs, Point rhs) {
        return lhs -= rhs;
    }
    friend Point operator*(Point p, Real k) {
        return p *= k;
    }
    friend Point operator/(Point p, Real k) {
        return p /= k;
    }
    friend Point operator*(Real k, Point p) {
        return p * k;
    }
    friend Point operator/(Real k, Point p) {
        return p / k;
    }
    friend bool operator==(Point lhs, Point rhs) {
        return eq(lhs.x, rhs.x) && eq(lhs.y, rhs.y);
    }
    friend bool operator<(Point lhs, Point rhs) {
        if (eq(lhs.x, rhs.x)) return lt(lhs.y, rhs.y);
        return lt(lhs.x, rhs.x);
    }
    friend bool operator>(Point lhs, Point rhs) {
        return rhs < lhs;
    }
    friend std::istream& operator>>(std::istream& is, Point& p) {
        is >> p.x >> p.y;
        return is;
    }
    friend std::ostream& operator<<(std::ostream& os, Point& p) {
        os << p.x << ' ' << p.y;
        return os;
    }
};

using Points = std::vector<Point>;
using Polygon = Points;
using Vector = Point;

Real norm(Vector p) {
    return p.x * p.x + p.y * p.y;
}

Real abs(Vector p) {
    return std::sqrt(norm(p));
}

Real dot(Vector lhs, Vector rhs) {
    return lhs.x * rhs.x + lhs.y * rhs.y;
}

Real cross(Vector lhs, Vector rhs) {
    return lhs.x * rhs.y - lhs.y * rhs.x;
}

int ccw(Point p0, Point p1, Point p2) {
    Vector a = p1 - p0;
    Vector b = p2 - p0;

    if (cross(a, b) > EPS) return 1;

    if (cross(a, b) < -EPS) return -1;

    if (dot(a, b) < 0) return 2;

    if (norm(a) < norm(b)) return -2;

    return 0;
}

struct Circle {
    Real r;
    Point c;
    Circle() {}
    Circle(Real r, Point c): r(r), c(c) {}
};

struct Segment {
    Segment() {}
    Segment(Point p0, Point p1): p0(p0), p1(p1) {}
    Point p0, p1;
};

struct Line {
    Line() {}
    Line(Point p0, Point p1): p0(p0), p1(p1) {}
    explicit Line(Segment s): p0(s.p0), p1(s.p1) {}
    Point p0, p1;
};

Real distance(Point lhs, Point rhs) {
    return abs(rhs - lhs);
}

Real distance(Line l, Point p) {
    return std::abs(cross(l.p1 - l.p0, p - l.p0)) / abs(l.p1 - l.p0);
}

Real distance(Segment s, Point p) {
    if (dot(s.p1 - s.p0, p - s.p0) < 0) {
        return distance(p, s.p0);
    }
    if (dot(s.p0 - s.p1, p - s.p1) < 0) {
        return distance(p, s.p1);
    }
    return distance(Line(s), p);
}

bool intersect(Segment lhs, Segment rhs) {
    return ccw(lhs.p0, lhs.p1, rhs.p0) * ccw(lhs.p0, lhs.p1, rhs.p1) <= 0
           && ccw(rhs.p0, rhs.p1, lhs.p0) * ccw(rhs.p0, rhs.p1, lhs.p1) <= 0;
}

bool intersect(Segment s, Point p) {
    return ccw(s.p0, s.p1, p) == 0;
}

Real distance(Segment lhs, Segment rhs) {
    if (intersect(lhs, rhs)) {
        return Real(0);
    }
    return std::min({distance(lhs, rhs.p0), distance(lhs, rhs.p1), distance(rhs, lhs.p0), distance(rhs, lhs.p1)});
}

bool parallel(Vector lhs, Vector rhs) {
    return eq(cross(lhs, rhs), 0);
}

bool parallel(Segment lhs, Segment rhs) {
    return parallel(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

bool parallel(Line lhs, Line rhs) {
    return parallel(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

Point crosspoint(Line lhs, Line rhs) {
    Real a = cross(lhs.p1 - lhs.p0, rhs.p1 - rhs.p0);
    Real b = cross(lhs.p1 - lhs.p0, lhs.p1 - rhs.p0);
    return rhs.p0 + (rhs.p1 - rhs.p0) * b / a;
}

bool intersect(Line l, Segment s) {
    return ccw(l.p0, l.p1, s.p0) * ccw(l.p0, l.p1, s.p1) <= 0;
}

bool intersect(Circle c, Line l) {
    return lte(distance(l, c.c), c.r);
}

bool intersect(Circle c, Point p) {
    return eq(distance(c.c, p), c.r);
}

bool internal(Circle c, Point p) {
    return lt(distance(c.c, p), c.r);
}

bool intersect(Circle c, Segment s) {
    return lte(distance(s, c.c), c.r);
}

int intersect(Circle lhs, Circle rhs) {
    if (gt(lhs.r, rhs.r)) std::swap(lhs, rhs);
    Real d = distance(lhs.c, rhs.c);
    if (lt(lhs.r + rhs.r, d)) return 4;
    if (eq(lhs.r + rhs.r, d)) return 3;
    if (gt(lhs.r + d, rhs.r)) return 2;
    if (eq(lhs.r + d, rhs.r)) return 1;
    return 0;
}

bool orthogonal(Vector lhs, Vector rhs) {
    return eq(dot(lhs, rhs), 0);
}

bool orthogonal(Segment lhs, Segment rhs) {
    return orthogonal(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

bool orthogonal(Line lhs, Line rhs) {
    return orthogonal(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

Point crosspoint(Segment lhs, Segment rhs) {
    Real d0 = distance(Line(lhs.p0, lhs.p1), rhs.p0);
    Real d1 = distance(Line(lhs.p0, lhs.p1), rhs.p1);
    return rhs.p0 + (rhs.p1 - rhs.p0) * (d0 / (d0 + d1));
}

Real arg(Vector p) {
    return std::atan2(p.y, p.x);
}

Vector polar(Real a, Real r) {
    return Point(std::cos(r) * a, std::sin(r) * a);
}

Point rotate(Point p, Real t) {
    Point v = polar(1, t);
    return Point(p.x * v.x - p.y * v.y, p.x * v.y + p.y * v.x);
}

Real angle(Point p0, Point p1, Point p2) {
    Real a = arg(p0 - p1);
    Real b = arg(p2 - p1);
    if (gt(a, b)) std::swap(a, b);
    return std::min(b - a, 2 * PI - (b - a));
}

Points crosspoint(Circle lhs, Circle rhs) {
    Real d = abs(lhs.c - rhs.c);
    if (eq(d, lhs.r + rhs.r)) return {lhs.c + lhs.r * (rhs.c - lhs.c) / d};
    Real a = std::acos((lhs.r * lhs.r + d * d - rhs.r * rhs.r) / (2 * lhs.r * d));
    Real t = arg(rhs.c - lhs.c);
    return {lhs.c + polar(lhs.r, t + a), lhs.c + polar(lhs.r, t - a)};
}

Point projection(Segment s, Point p) {
    Vector a = p - s.p0;
    Vector b = s.p1 - s.p0;
    Real t = dot(a, b) / norm(b);
    return s.p0 + t * b;
}

Point projection(Line l, Point p) {
    Vector a = p - l.p0;
    Vector b = l.p1 - l.p0;
    Real t = dot(a, b) / norm(b);
    return l.p0 + t * b;
}

Point reflection(Segment s, Point p) {
    return p + (projection(s, p) - p) * Real(2);
}

Point reflection(Line l, Point p) {
    return p + (projection(l, p) - p) * Real(2);
}

Points crosspoint(Circle c, Line l) {
    Vector p = projection(l, c.c);
    Real t = std::sqrt(c.r * c.r - norm(c.c - p));
    if (eq(t, 0)) return {p};
    Vector e = (l.p1 - l.p0) / abs(l.p1 - l.p0);
    return {p + t * e, p + -t * e};
}

Real area(Polygon poly) {
    int n = poly.size();
    Real result = 0;
    for (int i = 0; i < n; i++) {
        result += cross(poly[i], poly[(i + 1) % n]);
    }
    return result / 2;
}

Real perimeter(Polygon poly) {
    int n = poly.size();
    Real result = 0;
    for (int i = 0; i < n; i++) {
        result += abs(poly[i] - poly[(i + 1) % n]);
    }
    return result;
}

bool convex(Polygon poly) {
    int n = poly.size();
    for (int i = 0; i < n; i++) {
        if (ccw(poly[i], poly[(i + 1) % n], poly[(i + 2) % n]) == -1) return false;
    }
    return true;
}

int contain(Polygon poly, Point p) {
    int n = poly.size();
    bool parity = false;
    for (int i = 0; i < n; i++) {
        Point a = poly[i] - p;
        Point b = poly[(i + 1) % n] - p;
        if (gt(a.y, b.y)) std::swap(a, b);
        if (lte(a.y, 0) && lt(0, b.y) && lt(cross(a, b), 0)) parity ^= true;
        if (eq(cross(a, b), 0) && lte(dot(a, b), 0)) return 1;
    }
    return (parity ? 2 : 0);
}

Polygon convex_hull(Points points) {
    std::sort(points.begin(), points.end(), [](Point lhs, Point rhs) {
        if (eq(lhs.x, rhs.x)) return lt(lhs.y, rhs.y);
        return lt(lhs.x, rhs.x);
    });
    int n = points.size();
    Points lower, upper;
    lower.push_back(points[n - 1]);
    lower.push_back(points[n - 2]);
    upper.push_back(points[0]);
    upper.push_back(points[1]);
    for (int i = n - 3; i >= 0; i--) {
        for (int m = lower.size(); m >= 2 && ccw(lower[m - 2], lower[m - 1], points[i]) >= 0; m--) {
            lower.pop_back();
        }
        lower.push_back(points[i]);
    }
    for (int i = 2; i < n; i++) {
        for (int m = upper.size(); m >= 2 && ccw(upper[m - 2], upper[m - 1], points[i]) >= 0; m--) {
            upper.pop_back();
        }
        upper.push_back(points[i]);
    }
    std::reverse(lower.begin(), lower.end());
    std::copy(std::next(upper.rbegin()), std::prev(upper.rend()), std::back_inserter(lower));
    return lower;
}

Polygon convex_cut(Polygon poly, Line l) {
    int n = poly.size();
    Polygon res;
    for (int i = 0; i < n; i++) {
        Point a = poly[i];
        Point b = poly[(i + 1) % n];
        if (ccw(l.p0, l.p1, a) != -1) res.push_back(a);
        if (ccw(l.p0, l.p1, a) * ccw(l.p0, l.p1, b) == -1) {
            res.push_back(crosspoint(l, Line(a, b)));
        }
    }
    return res;
}

Line bisector(Point p0, Point p1, Point p2) {
    return Line(p1, p1 + polar(1, angle(p0, p1, p2) / 2));
}

Circle incircle(Point p0, Point p1, Point p2) {
    Point c = crosspoint(bisector(p0, p1, p2), bisector(p1, p2, p0));
    Real r = std::abs(2 * area({p0, p1, p2}) / perimeter({p0, p1, p2}));
    return Circle(r, c);
}

Line perpendicular(Line l, Point p) {
    Vector v = l.p1 - l.p0;
    return Line(p, p + Vector(-v.y, v.x));
}

Line perpendicular_bisector(Segment s) {
    return perpendicular(Line(s), (s.p0 + s.p1) / 2);
}

Circle circumscribed_circle(Point p0, Point p1, Point p2) {
    Point c = crosspoint(perpendicular_bisector(Segment(p0, p1)), perpendicular_bisector(Segment(p0, p2)));
    return Circle(distance(p0, c), c);
}

Real area(Circle c) {
    return c.r * c.r * PI;
}

Points tangent(Circle c, Point p) {
    return crosspoint(c, Circle(std::sqrt(norm(c.c - p) - c.r * c.r), p));
}

int solve() {
    Polygon ps;
    for (int i = 0; i < 3; i++) {
        Point p;
        std::cin >> p;
        ps.push_back(p);
    }
    Point s, t;
    std::cin >> s >> t;
    if (contain(ps, s) ^ contain(ps, t)) {
        std::cout << "OK" << std::endl;
    } else {
        std::cout << "NG" << std::endl;
    }
    return 0;
}

int main() {
    int n;
    std::cin >> n;
    while (n--) solve();
}
accuracy: 1
time_ms: 20
memory_kb: 3336
final_rank: 14

code_snippet: #pragma region Macros

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,abm,mmx,avx,avx2")

#include <bits/extc++.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using namespace __gnu_pbds;

// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using Bint = mp::cpp_int;
// using Bdouble = mp::number<mp::cpp_dec_float<256>>;
// Bdouble Beps = 0.00000000000000000000000000000001; // 1e-32
// const bool equals(Bdouble a, Bdouble b) { return mp::fabs(a - b) < Beps; }

#define pb emplace_back
#define int ll
#define endl '\n'
// #define unordered_map<int, int> gp_hash_table<int, int, custom_hash> 

#define sqrt __builtin_sqrtl
#define cbrt __builtin_cbrtl
#define hypot __builtin_hypotl

#define next asdnext
#define prev asdprev

using ll = long long;
using ld = long double;
const ld PI = acosl(-1);
const int INF = 1 << 30;
const ll INFL = 1LL << 61;
// const int MOD = 998244353;
const int MOD = 1000000007;

const ld EPS = 1e-10;
const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }

const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1}; // → ↓ ← ↑ ↘ ↙ ↖ ↗
const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1};

struct Edge {
    int from, to, cost;
    Edge() : from(-1), to(-1), cost(-1) {}
    Edge(int to, int cost) : to(to), cost(cost) {}
    Edge(int from, int to, int cost) : from(from), to(to), cost(cost) {}
    bool operator ==(const Edge& e) {
        return this->from == e.from && this->to == e.to && this->cost == e.cost;
    }
    bool operator !=(const Edge& e) {
        return this->from != e.from or this->to != e.to or this->cost != e.cost;
    }
};

chrono::system_clock::time_point start;
__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    start = chrono::system_clock::now();
}

random_device seed_gen;
mt19937_64 rng(seed_gen());
uniform_int_distribution<int> dist_x(0, 1e9);
struct RNG {
    unsigned Int(unsigned l, unsigned r) {
        return dist_x(rng) % (r - l + 1) + l;
    }
    ld Double() {
        return ld(dist_x(rng)) / 1e9;
    }
} rnd;

using i64 = ll;
// using i64 = uint64_t;
// bit演算, x==0の場合は例外処理した方がよさそう. 区間は [l, r)
i64 lrmask(i64 l, i64 r) { return (1LL << r) - (1LL << l); }
i64 sub_bit(i64 x, i64 l, i64 r) { i64 b = x & ((1LL << r) - (1LL << l)); return b >> l; } // r溢れ可
i64 bit_width(i64 x) { return 64 - __builtin_clzll(x) + (x == 0); }

i64 popcount(i64 x) { return __builtin_popcountll(x); }
i64 popcount(i64 x, i64 l, i64 r) { return __builtin_popcountll(sub_bit(x, l, r)); }
i64 unpopcount(i64 x) { return bit_width(x) - __builtin_popcountll(x); }
i64 unpopcount(i64 x, i64 l, i64 r) { return r - l - __builtin_popcountll(sub_bit(x, l, r)); }
bool is_pow2(i64 x) { return __builtin_popcountll(x) == 1; }

i64 top_bit(i64 x) { return 63 - __builtin_clzll(x);} // 2^kの位 (x > 0)
i64 bot_bit(i64 x) { return __builtin_ctz(x);} // 2^kの位 (x > 0)
// i64 next_bit(i64 x, i64 k) { return 0; }
// i64 prev_bit(i64 x, i64 k) { return 0; }
// i64 kth_bit(i64 x, i64 k) { return 0; }
i64 MSB(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // mask
i64 LSB(i64 x) { return (x & -x); } // mask

i64 countl_zero(i64 x) { return __builtin_clzll(x); }
i64 countl_one(i64 x) {
    i64 ret = 0, k = 63 - __builtin_clzll(x);
    while (k != -1 && (x & (1LL << k))) { k--; ret++; }
    return ret;
}
i64 countr_zero(i64 x) { return __builtin_ctzll(x); } // x==0のとき64が返ることに注意
i64 countr_one(i64 x) { i64 ret = 0; while (x & 1) { x >>= 1; ret++; } return ret; }

i64 floor_log2(i64 x) { if (x == 0) return 0; return 63 - __builtin_clzll(x); }
i64 bit_floor(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // MSBと同じ
i64 ceil_log2(i64 x) { if (x == 0) return 0; return 64 - __builtin_clzll(x - 1); }
i64 bit_ceil(i64 x) { if (x == 0) return 0; return 1LL << (64 - __builtin_clzll(x - 1)); }

i64 rotl(i64 x, i64 k) { // 有効bit内でrotate. オーバーフロー注意
    i64 w = bit_width(x); k %= w;
    return ((x << k) | (x >> (w - k))) & ((1LL << w) - 1);
}
// i64 rotl(i64 x, i64 l, i64 m, i64 r) {}
i64 rotr(i64 x, i64 k) {
    i64 w = bit_width(x); k %= w;
    return ((x >> k) | (x << (w - k))) & ((1LL << w) - 1);
}
// i64 rotr(i64 x, i64 l, i64 m, i64 r) {}
i64 bit_reverse(i64 x) { // 有効bit内で左右反転
    i64 r = 0, w = bit_width(x);
    for (i64 i = 0; i < w; i++) r |= ((x >> i) & 1) << (w - i - 1);
    return r;
}
// i64 bit_reverse(i64 x, i64 l, i64 r) { return 0; }

bool is_palindrome(i64 x) { return x == bit_reverse(x); }
bool is_palindrome(i64 x, i64 l, i64 r) { i64 b = sub_bit(x, l, r); return b == bit_reverse(b); }
i64 concat(i64 a, i64 b) { return (a << bit_width(b)) | b; } // オーバーフロー注意
i64 erase(i64 x, i64 l, i64 r) { return x>>r<<l | x&(1LL<<l - 1); } // [l, r) をカット

i64 hamming(i64 a, i64 b) { return __builtin_popcountll(a ^ b); }
i64 hamming(i64 a, i64 b, i64 l, i64 r) { return __builtin_popcountll(sub_bit(a, l, r) ^ sub_bit(b, l, r)); }
i64 compcount(i64 x) { return (__builtin_popcountll(x ^ (x >> 1)) + (x & 1)) / 2; }
i64 compcount2(i64 x) { return compcount(x & (x >> 1)); } // 長さ2以上の連結成分の個数
i64 adjacount(i64 x) { return __builtin_popcountll(x & (x >> 1)); } // 隣接する1のペアの個数

i64 next_combination(i64 x) {
    i64 t = x | (x - 1); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(x) + 1));
}


__int128_t POW(__int128_t x, int n) {
    __int128_t ret = 1;
    assert(n >= 0);
    if (x == 1 or n == 0) ret = 1;
    else if (x == -1 && n % 2 == 0) ret = 1; 
    else if (x == -1) ret = -1; 
    else if (n % 2 == 0) {
        assert(x < INFL);
        ret = POW(x * x, n / 2);
    } else {
        assert(x < INFL);
        ret = x * POW(x, n - 1);
    }
    return ret;
}
int per(int x, int y) { // x = qy + r (0 <= r < y) を満たすq
    assert(y != 0);
    if (x >= 0 && y > 0) return x / y;
    if (x >= 0 && y < 0) return x / y - (x % y < 0);
    if (x < 0 && y < 0) return x / y + (x % y < 0);
    return x / y - (x % y < 0); //  (x < 0 && y > 0) 
}
int mod(int x, int y) { // x = qy + r (0 <= r < y) を満たすr
    assert(y != 0);
    if (x >= 0) return x % y;
    __int128_t ret = x % y; // (x < 0)
    ret += (__int128_t)abs(y) * INFL;
    ret %= abs(y);
    return ret;
}
int floor(int x, int y) { // (ld)x / y 以下の最大の整数
    assert(y != 0);
    if (y < 0) x = -x, y = -y;
    return x >= 0 ? x / y : (x + 1) / y - 1;
}
int ceil(int x, int y) { // (ld)x / y 以上の最小の整数
    assert(y != 0);
    if (y < 0) x = -x, y = -y;
    return x > 0 ? (x - 1) / y + 1 : x / y;
}
int round(int x, int y) {
    assert(y != 0);
    return (x * 2 + y) / (y * 2);
}
int round(int x, int y, int k) { // (ld)(x/y)を10^kの位に関して四捨五入
    assert(y != 0); // TODO
    return INF;
}
int round2(int x, int y) { // 五捨五超入 // 未verify
    assert(y != 0);
    if (y < 0) y = -y, x = -x;
    int z = z / y;
    if ((z * 2 + 1) * y <= y * 2) z++;
    return z;
}
// int round(ld x, int k) { // xを10^kの位に関して四捨五入
// }
// int floor(ld x, int k) { // xを10^kの位に関してflooring
// }
// int ceil(ld x, int k) { // xを10^kの位に関してceiling
// }
// int kth(int x, int y, int k) { // x / yの10^kの位の桁
// }
int floor(ld x, ld y) { // 誤差対策TODO
    assert(!equals(y, 0));
    return floor(x / y);
    // floor(x) = ceil(x - 1) という話も
}
int ceil(ld x, ld y) { // 誤差対策TODO // ceil(p/q) = -floor(-(p/q))らしい
    assert(!equals(y, 0));
    return ceil(x / y);
    // ceil(x) = floor(x + 1)
}
int perl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす q
    // 未verify. 誤差対策TODO. EPS外してもいいかも。
    assert(!equals(y, 0));
    if (x >= 0 && y > 0) return floor(x / y)+EPS;
    if (x >= 0 && y < 0) return -floor(x / fabs(y));
    if (x < 0 && y < 0) return floor(x / y) + (x - floor(x/y)*y < -EPS);
    return floor(x / y) - (x - floor(x/y)*y < -EPS); //  (x < 0 && y > 0) 
}
ld modl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす r
    // 未verify. 誤差対策TODO. -0.0が返りうる。
    assert(!equals(y, 0));
    if (x >= 0) return x - fabs(y)*fabs(per(x, y));
    return x - fabs(y)*floor(x, fabs(y));
}
int seisuu(ld x) { return (int)x; } // 整数部分. 誤差対策TODO
int modf(ld x) {
	if (x < 0) return ceill(x);
	else return floorl(x);
}
// 正なら+EPS, 負なら-EPSしてから、文字列に直して小数点以下を捨てる?
int seisuu(int x, int y) {
    assert(y != 0);
    return x / y;
}
int seisuu(ld x, ld y) { // 誤差対策TODO
    assert(!equals(y, 0));
    return (int)(x / y);
}

template <class T> pair<T, T> max(const pair<T, T> &a, const pair<T, T> &b) {
    if (a.first > b.first or a.first == b.first && a.second > b.second) return a;
    return b;
}
template <class T> pair<T, T> min(const pair<T, T> &a, const pair<T, T> &b) {
    if (a.first < b.first or a.first == b.first && a.second < b.second) return a;
    return b;
}

template <class T> bool chmax(T &a, const T& b) {
    if (a < b) { a = b; return true; } return false;
}
template <class T> bool chmin(T &a, const T& b) {
    if (a > b) { a = b; return true; } return false;
}
template <class T> T mid(T a, T b, T c) { // 誤差対策TODO
    return a + b + c - max({a, b, c}) - min({a, b, c});
}
template <class T> void Sort(T &a, T &b, bool rev = false) { 
    if (rev == false) {  // TODO テンプレート引数
        if (a > b) swap(a, b);
    } else {
        if (b > a) swap(b, a);
    }
}
template <class T> void sort(T &a, T &b, T &c, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c); if (b > c) swap(b, c);
    } else {
        if (c > b) swap(c, b); if (c > a) swap(c, a); if (b > a) swap(b, a);
    }
}
template <class T> void sort(T &a, T &b, T &c, T &d, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c);  if (a > d) swap(a, d);
        if (b > c) swap(b, c); if (b > d) swap(b, d); if (c > d) swap(c, d);
    } else {
        if (d > c) swap(d, c); if (d > b) swap(d, b); if (d > a) swap(d, a);
        if (c > b) swap(c, b); if (c > a) swap(c, a); if (b > a) swap(b, a);
    }
}

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

class Compress {
public:
    int sz = 0;
    // gp_hash_table<int, int, custom_hash> Z, UZ;
    unordered_map<int, int> Z;    // 元の値 -> 圧縮した値
    unordered_map<int, int> UZ;   // 圧縮した値 -> 元の値

    Compress(const vector<int> &V, int base = 0) {
        this->sz = base;
        set<int> s(V.begin(), V.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
    
    Compress(const vector<int> &V1, const vector<int> &V2, int base = 0) {
        this->sz = base;
        vector<int> V3 = V2;
        V3.insert(V3.end(), V1.begin(), V1.end());
        set<int> s(V3.begin(), V3.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    Compress(const vector<int> &V1, const vector<int> &V2, const vector<int> &V3, int base = 0) {
        this->sz = base;
        vector<int> V4 = V1;
        V4.insert(V4.end(), V2.begin(), V2.end());
        V4.insert(V4.end(), V3.begin(), V3.end());
        set<int> s(V4.begin(), V4.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    Compress(const vector<int> &V1, const vector<int> &V2,
            const vector<int> &V3, const vector<int> &V4, int base = 0) {
        this->sz = base;
        vector<int> V5 = V1;
        V5.insert(V5.end(), V2.begin(), V2.end());
        V5.insert(V5.end(), V3.begin(), V3.end());
        V5.insert(V5.end(), V4.begin(), V4.end());
        set<int> s(V5.begin(), V5.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    vector<int> zip(const vector<int> &V) {
        vector<int> ret = V;
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = Z[ret[i]];
        }
        return ret;
    }

    vector<int> unzip(const vector<int> &V) {
        vector<int> ret = V;
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = UZ[ret[i]];
        }
        return ret;
    }

    int size() { return sz; }

    int encode(int x) { return Z[x]; }
    int decode(int x) {
        if (UZ.find(x) == UZ.end()) return -1; // xが元の配列に存在しないとき
        return UZ[x];
    }
};

class UnionFind {
public:
	UnionFind() = default;
    UnionFind(int N) : par(N), sz(N, 1) {
        iota(par.begin(), par.end(), 0);
    }
	int root(int x) {
		if (par[x] == x) return x;
		return (par[x] = root(par[x]));
	}
	bool unite(int x, int y) {
		int rx = root(x);
		int ry = root(y);
        if (rx == ry) return false;
		if (sz[rx] < sz[ry]) swap(rx, ry);
		sz[rx] += sz[ry];
		par[ry] = rx;
        return true;
	}
	bool issame(int x, int y) { return (root(x) == root(y)); }
	int size(int x) { return sz[root(x)]; }
    vector<vector<int>> groups(int N) {
        vector<vector<int>> G(N);
        for (int x = 0; x < N; x++) {
            G[root(x)].push_back(x);
        }
		G.erase( remove_if(G.begin(), G.end(),
            [&](const vector<int>& V) { return V.empty(); }), G.end());
        return G;
    }
private:
	vector<int> par, sz;
};

template<typename T>
struct BIT {
    int N;             // 要素数
    vector<T> bit[2];  // データの格納先
    BIT(int N_, int x = 0) {
        N = N_ + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        if (x != 0) {
            for (int i = 0; i < N; i++) add(i, x);
        }
    }
    BIT(const vector<int> &A) {
        N = A.size() + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        for (int i = 0; i < (int)A.size(); i++) add(i, A[i]);
    }
    void add_sub(int p, int i, T x) {
        while (i < N) { bit[p][i] += x; i += (i & -i); }
    }
    void add(int l, int r, T x) {
        add_sub(0, l + 1, -x * l); add_sub(0, r + 1, x * r);
        add_sub(1, l + 1, x); add_sub(1, r + 1, -x);
    }
    void add(int i, T x) { add(i, i + 1, x); }
    T sum_sub(int p, int i) {
        T ret = 0;
        while (i > 0) { ret += bit[p][i]; i -= (i & -i); }
        return ret;
    }
    T sum(int i) { return sum_sub(0, i) + sum_sub(1, i) * i; }
    T sum(int l, int r) { return sum(r) - sum(l); }
    T get(int i) { return sum(i, i + 1); }
    void set(int i, T x) { T s = get(i); add(i, -s + x); }
};

template<int mod> class Modint {
public:
    int val = 0;
    Modint(int x = 0) { while (x < 0) x += mod; val = x % mod; }
    Modint(const Modint &r) { val = r.val; }

    Modint operator -() { return Modint(-val); } // 単項
    Modint operator +(const Modint &r) { return Modint(*this) += r; }
    Modint operator +(const int &q) { Modint r(q); return Modint(*this) += r; }
    Modint operator -(const Modint &r) { return Modint(*this) -= r; }
    Modint operator -(const int &q) { Modint r(q); return Modint(*this) -= r; }
    Modint operator *(const Modint &r) { return Modint(*this) *= r; }
    Modint operator *(const int &q) { Modint r(q); return Modint(*this) *= r; }
    Modint operator /(const Modint &r) { return Modint(*this) /= r; }
    Modint operator /(const int &q) { Modint r(q); return Modint(*this) /= r; }
    
    Modint& operator ++() { val++; if (val >= mod) val -= mod; return *this; } // 前置
    Modint operator ++(signed) { ++*this; return *this; } // 後置
    Modint& operator --() { val--; if (val < 0) val += mod; return *this; }
    Modint operator --(signed) { --*this; return *this; }
    Modint &operator +=(const Modint &r) { val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator +=(const int &q) { Modint r(q); val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator -=(const Modint &r) { if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator -=(const int &q) { Modint r(q);  if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator *=(const Modint &r) { val = val * r.val % mod; return *this; }
    Modint &operator *=(const int &q) { Modint r(q); val = val * r.val % mod; return *this; }
    Modint &operator /=(const Modint &r) {
        int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    Modint &operator /=(const int &q) {
        Modint r(q); int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    bool operator ==(const Modint& r) { return this -> val == r.val; }
    bool operator <(const Modint& r) { return this -> val < r.val; }
    bool operator >(const Modint& r) { return this -> val > r.val; }
    bool operator !=(const Modint& r) { return this -> val != r.val; }
};

using mint = Modint<MOD>;

istream &operator >>(istream &is, mint& x) {
    int t; is >> t; x = t; return (is);
}
ostream &operator <<(ostream &os, const mint& x) {
    return os << x.val;
}
mint modpow(const mint &x, int n) {
    if (n < 0) return (mint)1 / modpow(x, -n); // 未verify
    assert(n >= 0);
    if (n == 0) return 1;
    mint t = modpow(x, n / 2);
    t = t * t;
    if (n & 1) t = t * x;
    return t;
}

int modpow(__int128_t x, int n, int mod) {
    assert(n >= 0 && mod > 0); // TODO: n <= -1
    __int128_t ret = 1;
    while (n > 0) {
        if (n % 2 == 1) ret = ret * x % mod;
        x = x * x % mod;
        n /= 2;
    }
    return ret;
}
int modinv(__int128_t x, int mod) {
    assert(mod > 0);
    // assert(x > 0);
    if (x == 1 or x == 0) return 1;
    return mod - modinv(mod % x, mod) * (mod / x) % mod;
}

istream &operator >>(istream &is, __int128_t& x) {
    string S; is >> S;
    __int128_t ret = 0;
    int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9')
            ret = ret * 10 + S[i] - '0';
    x = ret * f;
    return (is);
}
ostream &operator <<(ostream &os, __int128_t x) {
    ostream::sentry s(os);
    if (s) {
        __uint128_t tmp = x < 0 ? -x : x;
        char buffer[128]; char *d = end(buffer);
        do {
            --d; *d = "0123456789"[tmp % 10]; tmp /= 10;
        } while (tmp != 0);
        if (x < 0) { --d; *d = '-'; }
        int len = end(buffer) - d;
        if (os.rdbuf()->sputn(d, len) != len) os.setstate(ios_base::badbit);
    }
    return os;
}

__int128_t stoll(string &S) {
    __int128_t ret = 0; int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9') ret = ret * 10 + S[i] - '0';
    return ret * f;
}
__int128_t gcd(__int128_t a, __int128_t b) { return b ? gcd(b, a % b) : a; }
__int128_t lcm(__int128_t a, __int128_t b) {
    return a / gcd(a, b) * b;
    // lcmが__int128_tに収まる必要あり
}

string to_string(ld x, int k) { // xの小数第k位までをstring化する
    assert(k >= 0);
    stringstream ss;
    ss << setprecision(k + 2) << x;
    string s = ss.str();
    if (s.find('.') == string::npos) s += '.';
    int pos = s.find('.');
    for (int i = 0; k >= (int)s.size() - 1 - pos; i++) s += '0';
    s.pop_back();
    if (s.back() == '.') s.pop_back();
    return s;

    // stringstream ss; // 第k+1位を四捨五入して第k位まで返す
    // ss << setprecision(k + 1) << x;
    // string s = ss.str();
    // if (s.find('.') == string::npos) s += '.';
    // int pos = s.find('.');
    // for (int i = 0; k > (int)s.size() - 1 - pos; i++) s += '0';
    // if (s.back() == '.') s.pop_back();
    // return s;
}
string to_string(__int128_t x) {
    string ret = "";
    if (x < 0) { ret += "-"; x *= -1; }
    while (x) { ret += (char)('0' + x % 10); x /= 10; }
    reverse(ret.begin(), ret.end());
    return ret;
}
string to_string(char c) { string s = ""; s += c; return s; }

template<class T> size_t HashCombine(const size_t seed,const T &v) {
    return seed^(hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2));
}
template<class T,class S> struct hash<pair<T,S>>{
    size_t operator()(const pair<T,S> &keyval) const noexcept {
        return HashCombine(hash<T>()(keyval.first), keyval.second);
    }
};
template<class T> struct hash<vector<T>>{
    size_t operator()(const vector<T> &keyval) const noexcept {
        size_t s=0;
        for (auto&& v: keyval) s=HashCombine(s,v);
        return s;
    }
};
template<int N> struct HashTupleCore{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{
        size_t s=HashTupleCore<N-1>()(keyval);
        return HashCombine(s,get<N-1>(keyval));
    }
};
template <> struct HashTupleCore<0>{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; }
};
template<class... Args> struct hash<tuple<Args...>>{
    size_t operator()(const tuple<Args...> &keyval) const noexcept {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};

vector<mint> _fac, _finv, _inv;
void COMinit(int N) {
    _fac.resize(N + 1); _finv.resize(N + 1);  _inv.resize(N + 1);
    _fac[0] = _fac[1] = 1; _finv[0] = _finv[1] = 1; _inv[1] = 1;
    for (int i = 2; i <= N; i++) {
        _fac[i] = _fac[i-1] * mint(i);
        _inv[i] = -_inv[MOD % i] * mint(MOD / i);
        _finv[i] = _finv[i - 1] * _inv[i];
    }
}

mint FAC(int N) {
    if (N < 0) return 0; return _fac[N];
}
mint COM(int N, int K) {
    if (N < K) return 0; if (N < 0 or K < 0) return 0;
    return _fac[N] * _finv[K] * _finv[N - K];
}
mint PERM(int N, int K) {
    if (N < K) return 0; if (N < 0 or K < 0) return 0;
    return _fac[N] *  _finv[N - K];
}
mint NHK(int N, int K) { // initのサイズに注意
    if (N == 0 && K == 0)  return 1;
    return COM(N + K - 1, K);
}

#pragma endregion

vector<string> split_str(string S, char c) {
    vector<string> ret;
    stringstream ss;
    for (int i = 0; i < S.size(); i++) {
        if (S[i] == c) {
            ret.pb(ss.str());
            ss.str("");
            ss.clear();
        } else {
            ss << S[i];
        }
    }
    ret.pb(ss.str());
    return ret;
}

struct Point {
	double x, y;

	Point() {}
	Point(double x, double y) : x(x), y(y) {}

	Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }
	Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }
	Point operator*(const double& k) const { return Point(x * k, y * k); }
	Point operator/(const double& k) const { return Point(x / k, y / k); }

	friend istream& operator>>(istream& is, Point& p) {
		is >> p.x >> p.y;
		return is;
	}
	friend ostream& operator<<(ostream& os, Point& p) {
		os << p.x << " " << p.y;
		return os;
	}

	bool operator==(const Point& p) const { return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS); }
	bool operator<(const Point& p) const { return (x != p.x ? x < p.x : y < p.y); }
	// (x, y) の辞書順比較

	double norm() { return x * x + y * y; }
	double abs() { return sqrt(norm()); }
};

typedef Point Vector;

double radToDeg(double radian) { return radian * 180.0 / PI; }
double degToRad(double degree) { return degree * PI / 180.0; }

int sign(double x) { return x < -EPS ? -1 : x > EPS; } // -1(負)/0/1(正)

double norm(Vector a) { return a.x * a.x + a.y * a.y; }
double abs(Vector a) { return sqrt(norm(a)); }
double dist(Point a, Point b) { return sqrt(norm(a - b)); }
double dot(Vector a, Vector b) { return a.x * b.x + a.y * b.y; } // 内積
double cross(Vector a, Vector b) { return a.x * b.y - a.y * b.x; } // 外積

Vector orth(Vector p) { return {-p.y, p.x}; }

double arg(Vector p) { return atan2(p.y, p.x); } // 偏角
Point polar(double r, double a) { return Point(cos(a) * r, sin(a) * r); } // 極座標から直交座標への変換

bool isParallel(Vector a, Vector b) { return equals(cross(a, b), 0.0); }
bool isOrthogonal(Vector a, Vector b) { return equals(dot(a, b), 0.0); }
// bool isSameLine(Vector a, Vector b) { return equals(); }

struct EndPoint { // 端点の構造体(マンハッタン幾何)
	Point p;
	int seg, st; // 点のid, 点の種別

	EndPoint() {}
	EndPoint(Point p, int seg, int st) : p(p), seg(seg), st(st) {}

	bool operator<(const EndPoint& ep) const {
		if (p.y == ep.p.y) return st < ep.st;
		return p.y < ep.p.y;
	}
};

struct Segment {
	Point p1, p2;

	Segment() {}
	Segment(Point p1, Point p2) : p1(p1), p2(p2) {}

	friend istream& operator>>(istream& is, Segment& s) {
		is >> s.p1 >> s.p2;
		return is;
	}
};

struct Line {
	Point p1, p2;

	Line() {}
	Line(Point p1, Point p2) : p1(p1), p2(p2) {}
	// Ax + By = C
    Line(double A, double B, double C) {
        if (equals(A, 0)) {
            p1 = Point(0, C / B), p2 = Point(1, C / B);
        } else if (equals(B, 0)) {
            p2 = Point(C / A, 0), p2 = Point(C / A, 1);
        } else {
            p1 = Point(0, C / B), p2 = Point(C / A, 0);
        }
    }

	friend istream& operator>>(istream& is, Line& l) {
		is >> l.p1 >> l.p2;
		return is;
	}
};

bool isParallel(Segment S1, Segment S2) { return isParallel(S1.p2 - S1.p1, S2.p2 - S2.p1); }
bool isParallel(Line S1, Line S2) { return isParallel(S1.p2 - S1.p1, S2.p2 - S2.p1); }
bool isParallel(Line S1, Segment S2) { return isParallel(S1.p2 - S1.p1, S2.p2 - S2.p1); }
bool isParallel(Segment S1, Line S2) { return isParallel(S1.p2 - S1.p1, S2.p2 - S2.p1); }

bool isOrthogonal(Segment S1, Segment S2) { return isOrthogonal(S1.p2 - S1.p1, S2.p2 - S2.p1); }
bool isOrthogonal(Line S1, Line S2) { return isOrthogonal(S1.p2 - S1.p1, S2.p2 - S2.p1); }
bool isOrthogonal(Line S1, Segment S2) { return isOrthogonal(S1.p2 - S1.p1, S2.p2 - S2.p1); }
bool isOrthogonal(Segment S1, Line S2) { return isOrthogonal(S1.p2 - S1.p1, S2.p2 - S2.p1); }

// bool isSameLine(Segment S1, Segment S2) { return isSameLine(S1.p2 - S1.p1, S2.p2 - S2.p1); }
// bool isSameLine(Line S1, Line S2) { return isSameLine(S1.p2 - S1.p1, S2.p2 - S2.p1); }
// bool isSameLine(Line S1, Segment S2) { return isSameLine(S1.p2 - S1.p1, S2.p2 - S2.p1); }
// bool isSameLine(Segment S1, Line S2) { return isSameLine(S1.p2 - S1.p1, S2.p2 - S2.p1); }

bool onSegment(Segment S, Point p) {
	if (sign(cross(S.p1-p, S.p2-p)) != 0) return false;
  	if (sign(  dot(S.p1-p, S.p2-p))  > 0) return false;
	return true;
}
bool onLine(Line L, Point p) {
	if (sign(cross(L.p1-p, L.p2-p)) != 0) return false;
	return true;
}

Point project(Segment s, Point p) { // 点の射影
	Vector base = s.p2 - s.p1;
	double r = dot(p - s.p1, base) / base.norm();
	return s.p1 + base * r;
}

Point reflect(Segment s, Point p) { // 点の反射
	return p + (project(s, p) - p) * 2.0;
}

struct Circle {
	Point c;
	double r;

	Circle() {}
	Circle(Point c, double r) : c(c), r(r) {}
};

typedef vector<Point> Polygon;

int contains(Polygon G, Point p) {
	int N = G.size();
	bool x = false;
	for (int i = 0; i < N; i++) {
		Point a = G[i] - p;
		Point b = G[(i + 1) % N] - p;

		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
		if (a.y > b.y) swap(a, b);
		if (a.y < EPS && EPS < b.y && cross(a, b) > EPS) x = !x;
	}
	return (x ? 2 : 0);
}

signed main() {
    int N;
    cin >> N;
    for (int i = 0; i < N; i++) {
        Point p1, p2, p3;
        Segment S;
        cin >> p1 >> p2 >> p3 >> S;

        vector<Point> P = {p1, p2, p3};

        if (contains(P, S.p1) != contains(P, S.p2)) cout << "OK" << endl;
	    else cout << "NG" << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3504
final_rank: 10

code_snippet: #line 1 "test/AOJ/0143.test.cpp"
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0143"
#line 1 "template/template.hpp"
// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define elif else if
#define updiv(N, X) ((N + X - 1) / X)
#define sigma(a, b) ((a + b) * (b - a + 1) / 2)
struct fast_ios {
    fast_ios() {
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
    };
} fast_ios_;
template <typename T>
inline bool chmax(T& a, T b) { return ((a < b) ? (a = b, true) : (false)); }
template <typename T>
inline bool chmin(T& a, T b) { return ((a > b) ? (a = b, true) : (false)); }
constexpr int inf = 1 << 30;
constexpr ll INF = 1LL << 60;
constexpr int dx[] = {1, 0, -1, 0, 1, -1, 1, -1};
constexpr int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
constexpr int mod = 998244353;
constexpr int MOD = 1e9 + 7;
#line 1 "geomeny/geomeny-template.hpp"
using DD = long double;     // to be set appropriately
const DD EPS = 1e-10;  // to be set appropriately
const DD PI = acosl(-1.0);
DD torad(int deg) { return (DD)(deg)*PI / 180; }
DD todeg(DD ang) { return ang * 180 / PI; }

/* Point */
struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream &operator<<(ostream &s, const Point &p) { return s << '(' << p.x << ", " << p.y << ')'; }
};
inline Point operator+(const Point &p, const Point &q) { return Point(p.x + q.x, p.y + q.y); }
inline Point operator-(const Point &p, const Point &q) { return Point(p.x - q.x, p.y - q.y); }
inline Point operator*(const Point &p, DD a) { return Point(p.x * a, p.y * a); }
inline Point operator*(DD a, const Point &p) { return Point(a * p.x, a * p.y); }
inline Point operator*(const Point &p, const Point &q) { return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x); }
inline Point operator/(const Point &p, DD a) { return Point(p.x / a, p.y / a); }
inline Point conj(const Point &p) { return Point(p.x, -p.y); }
inline Point rot(const Point &p, DD ang) { return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y); }
inline Point rot90(const Point &p) { return Point(-p.y, p.x); }
inline DD cross(const Point &p, const Point &q) { return p.x * q.y - p.y * q.x; }
inline DD dot(const Point &p, const Point &q) { return p.x * q.x + p.y * q.y; }
inline DD norm(const Point &p) { return dot(p, p); }
inline DD abs(const Point &p) { return sqrt(dot(p, p)); }
inline DD amp(const Point &p) {
    DD res = atan2(p.y, p.x);
    if (res < 0) res += PI * 2;
    return res;
}
inline bool eq(const Point &p, const Point &q) { return abs(p - q) < EPS; }
inline bool operator<(const Point &p, const Point &q) { return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y); }
inline bool operator>(const Point &p, const Point &q) { return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y); }
inline Point operator/(const Point &p, const Point &q) { return p * conj(q) / norm(q); }

/* Line */
struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream &operator<<(ostream &s, const Line &l) { return s << '{' << l[0] << ", " << l[1] << '}'; }
};

/* Circle */
struct Circle : Point {
    DD r;
    Circle(Point p = Point(0.0, 0.0), DD r = 0.0) : Point(p), r(r) {}
    friend ostream &operator<<(ostream &s, const Circle &c) { return s << '(' << c.x << ", " << c.y << ", " << c.r << ')'; }
};
#line 2 "geomeny/ccw.hpp"

// 粗
// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)、0：一直線上
int simple_ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b - a, c - a) > EPS) return 1;
    if (cross(b - a, c - a) < -EPS) return -1;
    return 0;
}

// 精
// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)
// 2：c-a-bの順に一直線上、-2：a-b-cの順に一直線上、0：a-c-bの順に一直線上
int ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b - a, c - a) > EPS) return 1;
    if (cross(b - a, c - a) < -EPS) return -1;
    if (dot(b - a, c - a) < -EPS) return 2;
    if (norm(b - a) < norm(c - a) - EPS) return -2;
    return 0;
}
#line 2 "geomeny/is-contain-in-the-triangle.hpp"

// 辺上については判定していない
bool is_contain(const Point &p, const Point &a, const Point &b, const Point &c) {
    int r1 = simple_ccw(p, b, c), r2 = simple_ccw(p, c, a), r3 = simple_ccw(p, a, b);
    if (r1 == 1 && r2 == 1 && r3 == 1) return true;
    if (r1 == -1 && r2 == -1 && r3 == -1) return true;
    return false;
}
#line 4 "test/AOJ/0143.test.cpp"

int main() {
    int N;
    cin >> N;
    for (int i = 0; i < N; i++) {
        Point a, b, c, d, e;
        cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y >> d.x >> d.y >> e.x >> e.y;
        if (is_contain(d, a, b, c) == is_contain(e, a, b, c)) {
            cout << "NG" << endl;
        } else {
            cout << "OK" << endl;
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3356
final_rank: 5

code_snippet: #line 1 "test/AOJ/0143.test.cpp"
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0143"
#line 1 "template/template.hpp"
// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define elif else if
#define updiv(N, X) ((N + X - 1) / X)
#define sigma(a, b) ((a + b) * (b - a + 1) / 2)
struct fast_ios {
    fast_ios() {
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
    };
} fast_ios_;
template <typename T>
inline bool chmax(T& a, T b) { return ((a < b) ? (a = b, true) : (false)); }
template <typename T>
inline bool chmin(T& a, T b) { return ((a > b) ? (a = b, true) : (false)); }
constexpr int inf = 1 << 30;
constexpr ll INF = 1LL << 60;
constexpr int dx[] = {1, 0, -1, 0, 1, -1, 1, -1};
constexpr int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
constexpr int mod = 998244353;
constexpr int MOD = 1e9 + 7;
#line 1 "geomeny/geomeny-template.hpp"
using DD = long double;     // to be set appropriately
const DD EPS = 1e-10;  // to be set appropriately
const DD PI = acosl(-1.0);
DD torad(int deg) { return (DD)(deg)*PI / 180; }
DD todeg(DD ang) { return ang * 180 / PI; }

/* Point */
struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream &operator<<(ostream &s, const Point &p) { return s << '(' << p.x << ", " << p.y << ')'; }
};
inline Point operator+(const Point &p, const Point &q) { return Point(p.x + q.x, p.y + q.y); }
inline Point operator-(const Point &p, const Point &q) { return Point(p.x - q.x, p.y - q.y); }
inline Point operator*(const Point &p, DD a) { return Point(p.x * a, p.y * a); }
inline Point operator*(DD a, const Point &p) { return Point(a * p.x, a * p.y); }
inline Point operator*(const Point &p, const Point &q) { return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x); }
inline Point operator/(const Point &p, DD a) { return Point(p.x / a, p.y / a); }
inline Point conj(const Point &p) { return Point(p.x, -p.y); }
inline Point rot(const Point &p, DD ang) { return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y); }
inline Point rot90(const Point &p) { return Point(-p.y, p.x); }
inline DD cross(const Point &p, const Point &q) { return p.x * q.y - p.y * q.x; }
inline DD dot(const Point &p, const Point &q) { return p.x * q.x + p.y * q.y; }
inline DD norm(const Point &p) { return dot(p, p); }
inline DD abs(const Point &p) { return sqrt(dot(p, p)); }
inline DD amp(const Point &p) {
    DD res = atan2(p.y, p.x);
    if (res < 0) res += PI * 2;
    return res;
}
inline bool eq(const Point &p, const Point &q) { return abs(p - q) < EPS; }
inline bool operator<(const Point &p, const Point &q) { return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y); }
inline bool operator>(const Point &p, const Point &q) { return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y); }
inline Point operator/(const Point &p, const Point &q) { return p * conj(q) / norm(q); }

/* Line */
struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream &operator<<(ostream &s, const Line &l) { return s << '{' << l[0] << ", " << l[1] << '}'; }
};

/* Circle */
struct Circle : Point {
    DD r;
    Circle(Point p = Point(0.0, 0.0), DD r = 0.0) : Point(p), r(r) {}
    friend ostream &operator<<(ostream &s, const Circle &c) { return s << '(' << c.x << ", " << c.y << ", " << c.r << ')'; }
};
#line 2 "geomeny/ccw.hpp"

// 粗
// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)、0：一直線上
int simple_ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b - a, c - a) > EPS) return 1;
    if (cross(b - a, c - a) < -EPS) return -1;
    return 0;
}

// 精
// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)
// 2：c-a-bの順に一直線上、-2：a-b-cの順に一直線上、0：a-c-bの順に一直線上
int ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b - a, c - a) > EPS) return 1;
    if (cross(b - a, c - a) < -EPS) return -1;
    if (dot(b - a, c - a) < -EPS) return 2;
    if (norm(b - a) < norm(c - a) - EPS) return -2;
    return 0;
}
#line 2 "geomeny/is-contain-in-the-triangle.hpp"

// 辺上については判定していない
bool is_contain(const Point &p, const Point &a, const Point &b, const Point &c) {
    int r1 = simple_ccw(p, b, c), r2 = simple_ccw(p, c, a), r3 = simple_ccw(p, a, b);
    if (r1 == 1 && r2 == 1 && r3 == 1) return true;
    if (r1 == -1 && r2 == -1 && r3 == -1) return true;
    return false;
}
#line 4 "test/AOJ/0143.test.cpp"

int main() {
    cout << fixed << setprecision(8);
    int N;
    cin >> N;
    for (int i = 0; i < N; i++) {
        Point a, b, c, d, e;
        cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y >> d.x >> d.y >> e.x >> e.y;
        if (is_contain(d, a, b, c) == is_contain(e, a, b, c)) {
            cout << "NG" << endl;
        } else {
            cout << "OK" << endl;
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3532
final_rank: 12

code_snippet: #line 1 "test/AOJ/0143.test.cpp"
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0143"
#line 1 "template/template.hpp"
// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define elif else if
#define updiv(N, X) ((N + X - 1) / X)
#define sigma(a, b) ((a + b) * (b - a + 1) / 2)
struct fast_ios {
    fast_ios() {
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
    };
} fast_ios_;
template <typename T>
inline bool chmax(T& a, T b) { return ((a < b) ? (a = b, true) : (false)); }
template <typename T>
inline bool chmin(T& a, T b) { return ((a > b) ? (a = b, true) : (false)); }
constexpr int inf = 1 << 30;
constexpr ll INF = 1LL << 60;
constexpr int dx[] = {1, 0, -1, 0, 1, -1, 1, -1};
constexpr int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
constexpr int mod = 998244353;
constexpr int MOD = 1e9 + 7;
#line 1 "geomeny/geomeny-template.hpp"
using DD = double;     // to be set appropriately
const DD EPS = 1e-10;  // to be set appropriately
const DD PI = acosl(-1.0);
DD torad(int deg) { return (DD)(deg)*PI / 180; }
DD todeg(DD ang) { return ang * 180 / PI; }

/* Point */
struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream &operator<<(ostream &s, const Point &p) { return s << '(' << p.x << ", " << p.y << ')'; }
};
inline Point operator+(const Point &p, const Point &q) { return Point(p.x + q.x, p.y + q.y); }
inline Point operator-(const Point &p, const Point &q) { return Point(p.x - q.x, p.y - q.y); }
inline Point operator*(const Point &p, DD a) { return Point(p.x * a, p.y * a); }
inline Point operator*(DD a, const Point &p) { return Point(a * p.x, a * p.y); }
inline Point operator*(const Point &p, const Point &q) { return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x); }
inline Point operator/(const Point &p, DD a) { return Point(p.x / a, p.y / a); }
inline Point conj(const Point &p) { return Point(p.x, -p.y); }
inline Point rot(const Point &p, DD ang) { return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y); }
inline Point rot90(const Point &p) { return Point(-p.y, p.x); }
inline DD cross(const Point &p, const Point &q) { return p.x * q.y - p.y * q.x; }
inline DD dot(const Point &p, const Point &q) { return p.x * q.x + p.y * q.y; }
inline DD norm(const Point &p) { return dot(p, p); }
inline DD abs(const Point &p) { return sqrt(dot(p, p)); }
inline DD amp(const Point &p) {
    DD res = atan2(p.y, p.x);
    if (res < 0) res += PI * 2;
    return res;
}
inline bool eq(const Point &p, const Point &q) { return abs(p - q) < EPS; }
inline bool operator<(const Point &p, const Point &q) { return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y); }
inline bool operator>(const Point &p, const Point &q) { return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y); }
inline Point operator/(const Point &p, const Point &q) { return p * conj(q) / norm(q); }

/* Line */
struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream &operator<<(ostream &s, const Line &l) { return s << '{' << l[0] << ", " << l[1] << '}'; }
};

/* Circle */
struct Circle : Point {
    DD r;
    Circle(Point p = Point(0.0, 0.0), DD r = 0.0) : Point(p), r(r) {}
    friend ostream &operator<<(ostream &s, const Circle &c) { return s << '(' << c.x << ", " << c.y << ", " << c.r << ')'; }
};
#line 2 "geomeny/ccw.hpp"

// 粗
// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)、0：一直線上
int simple_ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b - a, c - a) > EPS) return 1;
    if (cross(b - a, c - a) < -EPS) return -1;
    return 0;
}

// 精
// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)
// 2：c-a-bの順に一直線上、-2：a-b-cの順に一直線上、0：a-c-bの順に一直線上
int ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b - a, c - a) > EPS) return 1;
    if (cross(b - a, c - a) < -EPS) return -1;
    if (dot(b - a, c - a) < -EPS) return 2;
    if (norm(b - a) < norm(c - a) - EPS) return -2;
    return 0;
}
#line 2 "geomeny/is-contain-in-the-triangle.hpp"

// 辺上については判定していない
bool is_contain(const Point &p, const Point &a, const Point &b, const Point &c) {
    int r1 = simple_ccw(p, b, c), r2 = simple_ccw(p, c, a), r3 = simple_ccw(p, a, b);
    if (r1 == 1 && r2 == 1 && r3 == 1) return true;
    if (r1 == -1 && r2 == -1 && r3 == -1) return true;
    return false;
}
#line 4 "test/AOJ/0143.test.cpp"

int main() {
    int N;
    cin >> N;
    for (int i = 0; i < N; i++) {
        Point a, b, c, d, e;
        cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y >> d.x >> d.y >> e.x >> e.y;
        if (is_contain(d, a, b, c) == is_contain(e, a, b, c)) {
            cout << "NG" << endl;
        } else {
            cout << "OK" << endl;
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3480
final_rank: 9

code_snippet: #include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define Inf 1000000000000000

const double eps = 1e-10;

template <typename T>
struct point{
	T x,y,rad,dir;
	
	point(T a=0.0,T b=0.0){
		x = a;
		y = b;
		fix_rd();
	}
	
	void update_x(T a,T b){
		x = a*x + b;
		fix_rd();
	}
	
	void update_x(T a){
		update_x(0.0,a);
	}
	
	void update_y(T a,T b){
		y = a*y + b;
		fix_rd();
	}
	
	void update_y(T a){
		update_y(0.0,a);
	}
	
	void update_rad(T a,T b){
		rad = a*rad + b;
		fix_xy();
	}
	
	void update_rad(T a){
		update_rad(0.0,a);
	}
	
	void update_dir(T a,T b){
		dir = a*dir + b;
		fix_xy();
	}

	void update_dir(T a){
		update_dir(0.0,a);
	}
	
	void fix_xy(){
		x = rad * cos(dir);
		y = rad * sin(dir);
		fix_rd();
	}
	
	void fix_rd(){
		rad = hypot(x,y);
		if(rad==0.0)dir=0.0;
		else dir = atan2(y,x);
		fix_zero();
	}
	
	void fix_zero(){
		if(abs(x)<eps)x = 0.0;
		if(abs(y)<eps)y = 0.0;
		if(abs(rad)<eps)rad = 0.0;
		if(abs(dir)<eps)dir = 0.0;
	}
	
	void normalize(){
		T s = size();
		update_x(1.0/s,0.0);
		update_y(1.0/s,0.0);
	}
	
	
	T get_dis(point<T> V){
		return hypot(x-V.x,y-V.y);
	}
	
	T size(){
		return get_dis(point<T>());
	}
	
	T angle_difference(point<T> V){
		double ret = dir - V.dir;
		if(ret<-acos(-1.0))ret = acos(-1.0)*2.0+ret;
		if(ret>acos(-1.0))ret=-acos(-1.0)*2.0+ret;
		return ret;
	}
	
	//中点
	point get_midpoint(point<T> V){
		V.update_x(0.5,x/2.0);
		V.update_y(0.5,y/2.0);
		return V;
	}
	
	T get_inner_product(point<T> V){
		return x*V.x+y*V.y;
	}
	
	T get_cross_product(point<T> V){
		return x*V.y-y*V.x;
	}
	
	point &operator+=(const point<T> &another){
		update_x(1,another.x);
		update_y(1,another.y);
		return (*this);
	}
	
	point &operator-=(const point<T> &another){
		update_x(1,-another.x);
		update_y(1,-another.y);
		return (*this);
	}
	
	point operator+(const point<T> &another)const{
		return (point(*this)+=another);
	}
	
	point operator-(const point<T> &another)const{
		return (point(*this)-=another);
	}
	
	void show(){
		cout<<x<<','<<y<<endl;
	}
};

//a+tx
template <typename T>
struct line{
	point<T> a,t;
	
	line(){
	}
	
	line(point<T> V1,point<T> V2){
		a=V1;
		t=V2-V1;
	}

	T get_signed_dis(point<T> V){
		point<double> PA = a-V;
		return PA.get_cross_product(t)/t.size();
	}
	
	T get_dis(point<T> V){
		return abs(get_signed_dis(V));
	}
	
	point<T> get_projection(point<T> P){
		T r = t.get_inner_product(P-a)/t.size();
		point<T> temp = t;
		temp.update_rad(0.0,r);
		return a+temp;
	}	
	
	point<T> get_cross_point(line<T> L){
		point<T> ret(1e20,1e20);
		if(abs(t.get_cross_product(L.t))<eps)return ret;

		T d0 = L.get_signed_dis(a);
		T d1 = L.get_signed_dis(a+t);
		point<T> temp = t;
		temp.x *= d0/(d1-d0);
		temp.y *= d0/(d1-d0);
		ret = a - temp;
		return ret;
	}
	
};

template <typename T>
struct segment{
	point<T> V1,V2;
	segment(point<T> a=point<T>(),point<T> b=point<T>()){
		V1=a;
		V2=b;
	}
	
	T get_dis(point<T> P){
		T ret = 1e20;
		line<T> L(V1,V2);
		point<T> Q = L.get_projection(P);
		if(Q.x+eps>min(V1.x,V2.x)&&Q.y+eps>min(V1.y,V2.y)
		&&Q.x<max(V1.x,V2.x)+eps&&Q.y<max(V1.y,V2.y)+eps)ret = min(ret,Q.get_dis(P));
		else{
			ret = min(ret,P.get_dis(V1));
			ret = min(ret,P.get_dis(V2));
		}
		return ret;
	}
	
	T get_dis(segment<T> l){
		if(get_cross_point(l).x<1e20)return 0.0;
		return min({get_dis(l.V1),get_dis(l.V2),l.get_dis(V1),l.get_dis(V2)});
	}
	
	point<T> get_cross_point(segment<T> l){
		line<T> L1(V1,V2),L2(l.V1,l.V2);
		point<T> P = L1.get_cross_point(L2);
		if(get_dis(P)<eps&&l.get_dis(P)<eps)return P;
		return point<T> (1e20,1e20);
	}
};

template <typename T>
struct triangle{
	point<T> V[3];
	
	triangle(point<T> V1,point<T> V2,point<T> V3){
		V[0] = V1;
		V[1] = V2;
		V[2] = V3;
	}
	
	point<T> get_circumcenter(){
		line<T> L1(V[0],V[1]);
		point<T> M1 = V[0].get_midpoint(V[1]);
		L1 = line<T>(M1,L1.b,L1.a);

		line<T> L2(V[1],V[2]);
		point<T> M2 = V[1].get_midpoint(V[2]);
		L2 = line<T>(M2,L2.b,L2.a);
				
		return L1.get_cross_point(L2);
	}
	
	T get_signed_area(){
		return ((V[1].x-V[0].x)*(V[2].y-V[0].y) - (V[2].x-V[0].x)*(V[1].y-V[0].y))/2.0;
	}
	
	T get_area(){
		return abs(get_signed_area());
	}
	
	bool is_inside(point<T> P){
		T S = triangle<T>(V[0],V[1],P).get_area() + triangle<T>(V[1],V[2],P).get_area() + triangle<T>(V[2],V[0],P).get_area();
		return abs(S - get_area())<eps;
	}
	
	bool is_clockwise(){
		point<T> X = V[1]-V[0],Y = V[2]-V[1];
		return X.x*Y.y-X.y*Y.x < 0.0;
	}
	
};

int main(){	

	int n;
	cin>>n;
	rep(_,n){
		vector<point<double>> p(3);
		rep(i,3){
			double x,y;
			cin>>x>>y;
			p[i] = point<double>(x,y);
		}
	
		triangle<double> t(p[0],p[1],p[2]);
		int xa = 0;
		rep(i,2){
			double x,y;
			cin>>x>>y;
			if(t.is_inside(point<double>(x,y)))xa ^= 1;
		}
		if(xa)cout<<"OK"<<endl;
		else cout<<"NG"<<endl;
	}
	
	return 0;
	
}
accuracy: 1
time_ms: 20
memory_kb: 3812
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

template<class T> struct point{
    T x, y;
    point(): x(0), y(0){}
    point(T a, T b): x(a), y(b){}
    point& operator += (const point& rhs) {x += rhs.x, y += rhs.y; return *this;}
    point& operator -= (const point& rhs) {x -= rhs.x, y -= rhs.y; return *this;}
    point& operator *= (const T& rhs) {x *= rhs, y *= rhs; return *this;}
    point& operator /= (const T& rhs) {x /= rhs, y /= rhs; return *this;}
    point operator +() const { return *this; }
    point operator -() const { return point() - *this; }
    friend point operator + (const point& lhs, const point& rhs) {return point(lhs) += rhs;}
    friend point operator - (const point& lhs, const point& rhs) {return point(lhs) -= rhs;}
    friend point operator * (const point& lhs, const T& rhs) {return point(lhs) *= rhs;}
    friend point operator * (const T& lhs, const point& rhs) {return point(rhs) *= lhs;}
    friend point operator / (const point& lhs, const T& rhs) {return point(lhs) /= rhs;}
    friend T operator * (const point& lhs, const point& rhs) {return lhs.x * rhs.x + lhs.y * rhs.y;}
    friend T operator ^ (const point& lhs, const point& rhs) {return lhs.x * rhs.y - lhs.y * rhs.x;}
    friend istream& operator >> (istream& os, point& rhs) noexcept {
        os >> rhs.x >> rhs.y;
        return os;
    }
    friend constexpr ostream& operator << (ostream &os, const point& rhs) noexcept {
        return os << '('<< rhs.x << ',' << rhs.y << ')';
    }
    double norm(){return sqrt(x * x + y * y);}
    T norm2(){return x * x + y * y;}
    int orthant(){//第何象限かのベクトルを返す(0,0は0象限とする)
        if(x == 0 && y == 0)return 0;
        if(y > 0)return (x > 0 ? 1 : 2);
        return (x > 0 ? 4 : 3);
    }
    //偏角ソート->ベクトルの大きさの小さい順の優先度
    friend bool operator < (point &lhs, point &rhs){
        int lo = lhs.orthant(), ro = rhs.orthant();
        if(lo != ro)return (lo < ro);
        T cv = (lhs ^ rhs);
        if(cv != 0)return (cv > 0);
        return (lhs.norm2() < rhs.norm2());
    }
};

int main(){
    int q;
    cin >> q;
    while(q--){
        vector<point<ll>> a(5);
        for(int i = 0; i < 5; i++)cin >> a[i];
        vector<ll> b(3), c(3);
        for(int i = 0; i < 3; i++){
            b[i] = ((a[3] - a[i]) ^ (a[(i + 1) % 3] - a[i]));
            c[i] = ((a[4] - a[i]) ^ (a[(i + 1) % 3] - a[i]));
        }
        sort(b.begin(), b.end());
        sort(c.begin(), c.end());
        if((b[0] * b[2] < 0) ^ (c[0] * c[2] < 2)){
            cout << "OK" << '\n';
        }else{
            cout << "NG" << '\n';
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3344
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i=0; i < (n); i++)

typedef double D;      // 座標値の型。doubleかlong doubleを想定
typedef complex<D> P;  // Point
typedef pair<P, P> L;  // Line
typedef vector<P> VP;
const D EPS = 1e-9;    // 許容誤差。問題によって変える
#define X real()
#define Y imag()
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)

D dot(P a, P b) {
  return (conj(a)*b).X;
}

D cross(P a, P b) {
  return (conj(a)*b).Y;
}

namespace std {
  bool operator<(const P a, const P b) {
    return a.X != b.X ? a.X < b.X : a.Y < b.Y;
  }
}

// 点が領域内部なら1、境界上なら2、外部なら0を返す
int inPolygon(const VP& ps, P p) {
  int n = ps.size();
  bool in = false;
  rep (i, n) {
    P a = ps[i] - p;
    P b = ps[(i + 1) % n] - p;
    if (EQ(cross(a,b), 0) && LE(dot(a,b), 0)) return 2;
    if (a.Y > b.Y) swap(a,b);
    if ((a.Y*b.Y < 0 || (a.Y*b.Y < EPS && b.Y > EPS)) && LE(cross(a, b), 0)) in = !in;
  }
  return in;
}

int main(){
  int N;
  cin >> N;
  for(int i=0;i<N;i++){
    VP vec(3);
    for(int j=0;j<3;j++){
      D x,y;
      cin >> x >> y;
      complex<D> c(x,y);
      vec[j] = c;
    }
    D x1,y1,x2,y2;
    cin >> x1 >> y1 >> x2 >> y2;
    complex<D> A(x1,y1),B(x2,y2);
    if(inPolygon(vec,A)+inPolygon(vec,B) == 1) cout << "OK" << endl;
    else cout << "NG" << endl;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 3508
final_rank: 17

code_snippet: #define _USE_MATH_DEFINES
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<list>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<iomanip>
#include<cctype>
#include<sstream>
#include<regex>
#include<bitset>
#include<random>
using namespace std;
#define int long long
#define uint unsigned long long
const int mod=1e9+7;
const int Mod=998244353;
const int inf=mod*mod;
const double eps=1e-9;
double cross(double x1,double y1,double x2,double y2){
	return x1*y2-x2*y1;
}
bool intri(double x1,double y1,double x2,double y2,double x3,double y3,double xp,double yp){
	double c1=cross(x2-x1,y2-y1,xp-x1,yp-y1),c2=cross(x3-x2,y3-y2,xp-x2,yp-y2),c3=cross(x1-x3,y1-y3,xp-x3,yp-y3);
	return c1>=0&&c2>=0&&c3>=0||c1<=0&&c2<=0&&c3<=0;
}
signed main(){
	int n,xp1,yp1,xp2,yp2,xp3,yp3,xk,yk,xs,ys;
	cin>>n;
	while(cin>>xp1>>yp1>>xp2>>yp2>>xp3>>yp3>>xk>>yk>>xs>>ys){
		bool k=intri(xp1,yp1,xp2,yp2,xp3,yp3,xk,yk),s=intri(xp1,yp1,xp2,yp2,xp3,yp3,xs,ys);
		cout<<(k!=s?"OK":"NG")<<endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3196
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

using real = double;
static constexpr real EPS = 1e-10;
struct Point {
    real x, y;
    Point& operator+=(const Point a) { x += a.x; y += a.y;  return *this; }
    Point& operator-=(const Point a) { x -= a.x; y -= a.y;  return *this; }
    Point& operator*=(const real k) { x *= k; y *= k;  return *this; }
    Point& operator/=(const real k) { x /= k; y /= k;  return *this; }
    Point operator+(const Point a) const {return Point(*this) += a; }
    Point operator-(const Point a) const {return Point(*this) -= a; }
    Point operator*(const real k) const {return Point(*this) *= k; }
    Point operator/(const real k) const {return Point(*this) /= k; }
    bool operator<(const Point &a) const { return (x != a.x ? x < a.x : y < a.y); }
    explicit Point(real a = 0, real b = 0) : x(a), y(b) {};
};

bool sorty(Point a, Point b){
    return (a.y != b.y ? a.y < b.y : a.x < b.x);
}

istream& operator>> (istream& s, Point& P){
    s >> P.x >> P.y;
    return s;
}

inline real dot(Point a, Point b){ return a.x*b.x + a.y*b.y; }
inline real cross(Point a, Point b){ return a.x*b.y - a.y*b.x; }
inline real abs(Point a){ return sqrt(dot(a, a)); }


real angle(Point A, Point B){
    return acos(dot(A, B)/abs(A)/abs(B));
}



static constexpr int COUNTER_CLOCKWISE = 1;
static constexpr int CLOCKWISE = -1;
static constexpr int ONLINE_BACK = 2;
static constexpr int ONLINE_FRONT = -2;
static constexpr int ON_SEGMENT = 0;

int ccw(Point a, Point b, Point c){
    b -= a; c -= a;
    if(cross(b, c) > EPS) return COUNTER_CLOCKWISE;
    if(cross(b, c) < -EPS) return CLOCKWISE;
    if(dot(b, c) < 0) return ONLINE_BACK;
    if(abs(b) < abs(c)) return ONLINE_FRONT;
    return ON_SEGMENT;
}
struct Segment {
    Point a, b;
    Segment(Point x, Point y) : a(x), b(y) {};
};

struct Line {
    Point a, b;
    Line(Point x, Point y) : a(x), b(y) {};
};

struct Circle{
    Point c; real r;
    Circle(Point c, real r): c(c), r(r) {};
};

using Polygon = vector<Point>;

bool intersect(Segment s, Segment t){
    return (ccw(s.a, s.b, t.a)*ccw(s.a, s.b, t.b) <= 0 &&
            ccw(t.a, t.b, s.a)*ccw(t.a, t.b, s.b) <= 0);
}

bool intersect(Segment s, Line t){
    int a = ccw(t.a, t.b, s.a), b = ccw(t.a, t.b, s.b);
    return (!(a&1) || !(b&1) || a != b);
}

Point polar(double r, double t){
    return Point(r*cos(t), r*sin(t));
}

double arg(Point p){
    return atan2(p.y, p.x);
}

static constexpr int CONTAIN = 0;
static constexpr int INSCRIBE = 1;
static constexpr int INTERSECT = 2;
static constexpr int CIRCUMSCRIBED = 3;
static constexpr int SEPARATE = 4;

int intersect(Circle c1, Circle c2){
    if(c1.r < c2.r) swap(c1, c2);
    real d = abs(c1.c-c2.c);
    real r = c1.r + c2.r;
    if(fabs(d-r) < EPS) return CIRCUMSCRIBED;
    if(d > r) return SEPARATE;
    if(fabs(d+c2.r-c1.r) < EPS) return INSCRIBE;
    if(d+c2.r < c1.r) return CONTAIN;
    return INTERSECT;
}

real distance(Line l, Point c){
    return abs(cross(l.b-l.a, c-l.a)/abs(l.b-l.a));
}


real distance(Segment s, Point c){
    if(dot(s.b-s.a, c-s.a) < EPS) return abs(c-s.a);
    if(dot(s.a-s.b, c-s.b) < EPS) return abs(c-s.b);
    return abs(cross(s.b-s.a, c-s.a)) / abs(s.a-s.b);
}

real distance(Segment s, Segment t){
    if(intersect(s, t)) return 0.0;
    return min({distance(s, t.a), distance(s, t.b),
                distance(t, s.a), distance(t, s.b)});
}


Point project(Line l, Point p){
    Point Q = l.b-l.a;
    return l.a + Q*(dot(p-l.a, Q) / dot(Q, Q));
}


Point project(Segment s, Point p){
    Point Q = s.b-s.a;
    return s.a + Q*(dot(p-s.a, Q) / dot(Q, Q));
}

Point refrect(Segment s, Point p){
    Point Q = project(s, p);
    return Q*2-p;
}

bool isOrthogonal(Segment s, Segment t){
    return fabs(dot(s.b-s.a, t.b-t.a)) < EPS;
}

bool isparallel(Segment s, Segment t){
    return fabs(cross(s.b-s.a, t.b-t.a)) < EPS;
}


Point crossPoint(Segment s, Segment t){
    real d1 = cross(s.b-s.a, t.b-t.a);
    real d2 = cross(s.b-s.a, s.b-t.a);
    if(fabs(d1) < EPS && fabs(d2) < EPS) return t.a;
    return t.a+(t.b-t.a)*d2/d1;
}

Point crossPoint(Line s, Line t){
    real d1 = cross(s.b-s.a, t.b-t.a);
    real d2 = cross(s.b-s.a, s.b-t.a);
    if(fabs(d1) < EPS && fabs(d2) < EPS) return t.a;
    return t.a+(t.b-t.a)*d2/d1;
}

Polygon crossPoint(Circle c, Line l){
    Point p = project(l, c.c), q = (l.b-l.a)/abs(l.b-l.a);
    if(abs(distance(l, c.c)-c.r) < EPS){
        return {p};
    }
    double k = sqrt(c.r*c.r-dot(p-c.c, p-c.c));
    return {p-q*k, p+q*k};
}

Polygon crossPoint(Circle c, Segment s){
    auto tmp = crossPoint(c, Line(s.a, s.b));
    Polygon ret;
    for (auto &&i : tmp) {
        if(distance(s, i) < EPS) ret.emplace_back(i);
    }
    return ret;
}


Polygon crossPoint(Circle c1, Circle c2){
    double d = abs(c1.c-c2.c);
    double a = acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    double t = arg(c2.c-c1.c);
    return {c1.c+polar(c1.r, t+a), c1.c+polar(c1.r, t-a)};
}

Polygon tangent(Circle c1, Point p){
    Circle c2 = Circle(p, sqrt(dot(c1.c-p, c1.c-p)-c1.r*c1.r));
    return crossPoint(c1, c2);
}
vector<Line> tangent(Circle c1, Circle c2){
    vector<Line> ret;
    if(c1.r < c2.r) swap(c1, c2);
    double k = dot(c1.c-c2.c, c1.c-c2.c);
    if(abs(k) < EPS) return {};
    Point u = (c2.c-c1.c)/sqrt(k);
    Point v(-u.y, u.x);
    for (auto &&i : {-1, 1}) {
        double h = (c1.r+i*c2.r)/sqrt(k);
        if(abs(h*h-1) < EPS){
            ret.emplace_back(c1.c+u*c1.r, c1.c+(u+v)*c1.r);
        }else if(h*h < 1){
            Point u2 = u*h, v2 = v*sqrt(1-h*h);
            ret.emplace_back(c1.c+(u2+v2)*c1.r, c2.c-(u2+v2)*c2.r*i);
            ret.emplace_back(c1.c+(u2-v2)*c1.r, c2.c-(u2-v2)*c2.r*i);
        }
    }
    return ret;
}

real area(Polygon v){
    if(v.size() < 3) return 0.0;
    real ans = 0.0;
    for (int i = 0; i < v.size(); ++i) {
        ans += cross(v[i], v[(i+1)%v.size()]);
    }
    return ans/2;
}

real area(Circle c, Polygon &v){
    int n = v.size();
    real ans = 0.0;
    Polygon u;
    for (int i = 0; i < n; ++i) {
        u.emplace_back(v[i]);
        auto q = crossPoint(c, Segment(v[i], v[(i+1)%n]));
        for (auto &&j : q) {
            u.emplace_back(j);
        }
    }
    for (int i = 0; i < u.size(); ++i) {
        Point A = u[i]-c.c, B = u[(i+1)%u.size()]-c.c;
        if(abs(A) >= c.r+EPS || abs(B) >= c.r+EPS){
            Point C = polar(1, arg(B)-arg(A));
            ans += c.r*c.r*arg(C)/2;
        }else {
            ans += cross(A, B)/2;
        }
    }
    return ans;
}

Polygon convex_hull(Polygon v){
    int n = v.size();
    sort(v.begin(),v.end(), sorty);
    int k = 0;
    Polygon ret(n*2);
    for (int i = 0; i < n; ++i) {
        while(k > 1 && cross(ret[k-1]-ret[k-2], v[i]-ret[k-1]) < 0) k--;
        ret[k++] = v[i];
    }
    for(int i = n-2, t=k; i >= 0; i--){
        while(k > t && cross(ret[k-1]-ret[k-2], v[i]-ret[k-1]) < 0) k--;
        ret[k++] = v[i];
    }
    ret.resize(k-1);
    return ret;
}

bool isconvex(Polygon v){
    int n = v.size();
    for (int i = 0; i < n; ++i) {
        if(ccw(v[(i+n-1)%n], v[i], v[(i+1)%n]) == CLOCKWISE) return false;
    }
    return true;
}

int contains(Polygon v, Point p){
    int n = v.size();
    bool x = false;
    static constexpr int IN = 2;
    static constexpr int ON = 1;
    static constexpr int OUT = 0;
    for (int i = 0; i < n; ++i) {
        Point a = v[i]-p, b = v[(i+1)%n]-p;
        if(fabs(cross(a, b)) < EPS && dot(a, b) < EPS) return ON;
        if(a.y > b.y) swap(a, b);
        if(a.y < EPS && EPS < b.y && cross(a, b) > EPS) x = !x;
    }
    return (x?IN:OUT);
}

real diameter(Polygon v){
    int n = v.size();
    if(n == 2) return abs(v[0]-v[1]);
    int i = 0, j = 0;
    for (int k = 0; k < n; ++k) {
        if(v[i] < v[k]) i = k;
        if(!(v[j] < v[k])) j = k;
    }
    real ret = 0;
    int si = i, sj = j;
    while(i != sj || j != si){
        ret = max(ret, abs(v[i]-v[j]));
        if(cross(v[(i+1)%n]-v[i], v[(j+1)%n]-v[j]) < 0.0) i = (i+1)%n;
        else j = (j+1)%n;
    }
    return ret;
}

Polygon convexCut(Polygon v, Line l){
    Polygon q;
    int n = v.size();
    for (int i = 0; i < n; ++i) {
        Point a = v[i], b = v[(i+1)%n];
        if(ccw(l.a, l.b, a) != -1) q.push_back(a);
        if(ccw(l.a, l.b, a)*ccw(l.a, l.b, b) < 0){
            q.push_back(crossPoint(Line(a, b), l));
        }
    }
    return q;
}

real closest_pair(Polygon &v, int l = 0, int r = -1){
    if(!(~r)){
        r = v.size();
        sort(v.begin(),v.end());
    }
    if(r - l < 2) {
        return abs(v.front()-v.back());
    }
    int mid = (l+r)/2;
    real p = v[mid].x;
    real d = min(closest_pair(v, l, mid), closest_pair(v, mid, r));
    inplace_merge(v.begin()+l, v.begin()+mid, v.begin()+r, sorty);
    Polygon u;
    for (int i = l; i < r; ++i) {
        if(fabs(v[i].x-p) >= d) continue;
        for (int j = 0; j < u.size(); ++j) {
            real dy = v[i].y-next(u.rbegin(), j)->y;
            if(dy >= d) break;
            d = min(d, abs(v[i]-*next(u.rbegin(), j)));
        }
        u.emplace_back(v[i]);
    }
    return d;
}

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        Point A, B, C, p, q;
        cin >> A >> B >> C >> p >> q;
        Polygon X{A, B, C};
        if(contains(X, p) != contains(X, q)) puts("OK");
        else puts("NG");
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3124
final_rank: 16

code_snippet: #include<iostream>
#include<algorithm>
#include <map>
#include <vector>
#include <stack>
#include<string>
#include<queue>
#include <regex>

using namespace std;

bool IsInTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int x0, int y0)
{
	int v1 = (x2 - x1) * (y0 - y1) - (y2 - y1) * (x0 - x1);
	int v2 = (x3 - x2) * (y0 - y2) - (y3 - y2) * (x0 - x2);
	int v3 = (x1 - x3) * (y0 - y3) - (y1 - y3) * (x0 - x3);

	return (v1 > 0 && v2 > 0 && v3 > 0) || (v1 < 0 && v2 < 0 && v3 < 0);
}

int main()
{
	int n;
	cin >> n;
	int xp1, yp1, xp2, yp2, xp3, yp3, xk, yk, xs, ys;
	for (size_t i = 0; i < n; i++)
	{
		cin >> xp1 >> yp1 >> xp2 >> yp2 >> xp3 >> yp3 >> xk >> yk >> xs >> ys;
		if (IsInTriangle(xp1, yp1, xp2, yp2, xp3, yp3, xk, yk) ^
			IsInTriangle(xp1, yp1, xp2, yp2, xp3, yp3, xs, ys))
			cout << "OK";
		else
			cout << "NG";
		cout << endl;
	}
	//system("pause");
}
accuracy: 1
time_ms: 10
memory_kb: 3088
final_rank: 2

code_snippet: /* is_contain_in_triangle.cpp
    点が三角形に含まれているか判定する

    verified:
        AOJ 0143
        http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0143
*/

#include <bits/stdc++.h>
using namespace std;

using D = double;

// P: 点,座標
using P = std::complex<D>;
namespace std {
bool operator<(const P& a, const P& b) { return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b); }
bool operator>(const P& a, const P& b) { return real(a) != real(b) ? real(a) > real(b) : imag(a) > imag(b); }
}  // namespace std
D dot(const P& a, const P& b) { return real(conj(a) * b); }    // 内積
D cross(const P& a, const P& b) { return imag(conj(a) * b); }  // 外積
D norm(const P& a) { return dot(a, a); }

const D PI = std::acos(-1);
const D EPS = 1e-10;
const D INF = 1e12;

int sgn(D a) { return (a < -EPS) ? -1 : (a > EPS) ? 1 : 0; }  // 比較

/* ccw(a,b,c)
    出力:
    1: a-bから見てcは反時計, -1: a-bから見てcは時計
    2: c-a-bで直線, -2: a-b-cで直線, 0: a-c-bで直線
*/
int ccw(const P& a, const P& b, const P& c) {
    if (sgn(cross(b - a, c - a)) == 1) return 1;         // 1: a-bから見てcは反時計
    if (sgn(cross(b - a, c - a)) == -1) return -1;       //-1: a-bから見てcは時計
    if (sgn(dot(b - a, c - a)) == -1) return 2;          // 2: c-a-bで直線
    if (sgn(norm(c - a) - norm(b - a)) == 1) return -2;  //-2: a-b-cで直線
    return 0;                                            // 0: a-c-bで直線
}

/* is_contain_in_triangle(p, a,b,c)
    p が 三角形abc に含まれていれば true を返す
*/
bool is_contain_in_triangle(const P& p, const P& a, const P& b, const P& c) {
    int r1 = ccw(p, b, c), r2 = ccw(p, c, a), r3 = ccw(p, a, b);
    if (r1 == r2 && r2 == r3 && (r1 == 1 || r1 == -1)) return true;
    return false;
}

int main() {
    int n;
    cin >> n;
    vector<int> ans(n);
    for (int i = 0; i < n; i++) {
        D x, y;
        P p[3];
        for (int j = 0; j < 3; j++) {
            cin >> x >> y;
            P tmp(x, y);
            p[j] = tmp;
        }
        cin >> x >> y;
        P k(x, y);
        cin >> x >> y;
        P s(x, y);

        if (is_contain_in_triangle(k, p[0], p[1], p[2]) ^ is_contain_in_triangle(s, p[0], p[1], p[2])) {
            ans[i] = 1;
        } else {
            ans[i] = 0;
        }
    }

    for (int i = 0; i < n; i++) {
        if (ans[i]) {
            cout << "OK\n";
        } else {
            cout << "NG\n";
        }
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3248
final_rank: 13

code_snippet: #include <iostream>
#include <cmath>
using namespace std;

struct Point{
  int x;
  int y;
}typedef point;

bool contain(point* p1, point* p2, point* p3, point* p);

int main(void){
  int n;
  cin>>n;
  int xp1,yp1,xp2,yp2,xp3,yp3,xk,yk,xs,ys;
  point p1,p2,p3,pk,ps;
  bool s,k;
  for(int i=0;i<n;i++){
    cin>>xp1>>yp1>>xp2>>yp2>>xp3>>yp3>>xk>>yk>>xs>>ys;
    p1.x=xp1;
    p1.y=yp1;
    p2.x=xp2;
    p2.y=yp2;
    p3.x=xp3;
    p3.y=yp3;
    pk.x=xk;
    pk.y=yk;
    ps.x=xs;
    ps.y=ys;
    s=contain(&p1,&p2,&p3,&ps);
    k=contain(&p1,&p2,&p3,&pk);
    if(s==k){
      cout<<"NG"<<endl;
    }
    else{
      cout<<"OK"<<endl;
    }
  }
  return 0;
}

bool contain(point* p1, point* p2, point* p3, point* p){
  int z1=0;
  int z2=0;
  z1+=(p1->x-p->x)*(p2->y-p->y)-(p2->x-p->x)*(p1->y-p->y);
  z2+=abs((p1->x-p->x)*(p2->y-p->y)-(p2->x-p->x)*(p1->y-p->y));
  z1+=(p2->x-p->x)*(p3->y-p->y)-(p3->x-p->x)*(p2->y-p->y);
  z2+=abs((p2->x-p->x)*(p3->y-p->y)-(p3->x-p->x)*(p2->y-p->y));
  z1+=(p3->x-p->x)*(p1->y-p->y)-(p1->x-p->x)*(p3->y-p->y);
  z2+=abs((p3->x-p->x)*(p1->y-p->y)-(p1->x-p->x)*(p3->y-p->y));
  if(abs(z1)==z2){
    return true;
  }
  else{
    return false;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 3088
final_rank: 7

code_snippet: #include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#define int long long
#define mod 1000000007
#define for0(i, n) for(int i = 0; i < (n); i++)
#define for1(i, n) for(int i = 1; i <= (n);i++)
using namespace std;
int get() { int r; cin >> r; return r; }
void solve() {
	double x[5], y[5], xs, ys, xt, yt;
	cin >> x[1] >> y[1] >> x[2] >> y[2] >> x[0] >> y[0] >> xs >> ys >> xt >> yt;
	int i1 = 1, i2 = 1, a = 1, b = 2, c = 0;
	for1(i, 3) {
		if (((x[a] - x[b]) * (ys - y[a]) - (y[a] - y[b]) * (xs - x[a])) * ((x[a] - x[b]) * (y[c] - y[a]) - (y[a] - y[b]) * (x[c] - x[a])) < 0)i1 = 0;
		if (((x[a] - x[b]) * (yt - y[a]) - (y[a] - y[b]) * (xt - x[a])) * ((x[a] - x[b]) * (y[c] - y[a]) - (y[a] - y[b]) * (x[c] - x[a])) < 0)i2 = 0;
		a++; b++; c++;
		if (a >= 3)a %= 3;
		if (b >= 3)b %= 3;
		if (c >= 3)c %= 3;
	}
	cout << (i1 + i2 == 1 ? "OK\n" : "NG\n");
}
signed main() {
	int n; cin >> n; for1(i, n)solve();
}
accuracy: 1
time_ms: 30
memory_kb: 3068
final_rank: 15

code_snippet: #include <bits/stdc++.h>

using namespace std;

class Point {
public:
	int x, y;
};

Point PointData[5];


int isExistTriangle(const Point& p) {

	int r1 = (PointData[1].x - PointData[0].x) * (p.y - PointData[0].y) - (p.x - PointData[0].x) * (PointData[1].y - PointData[0].y);
	int r2 = (PointData[2].x - PointData[1].x) * (p.y - PointData[1].y) - (p.x - PointData[1].x) * (PointData[2].y - PointData[1].y);
	int r3 = (PointData[0].x - PointData[2].x) * (p.y - PointData[2].y) - (p.x - PointData[2].x) * (PointData[0].y - PointData[2].y);

	if (r1 > 0 && r2 > 0 && r3 > 0) {
		return 1;
	}
	if (r1 < 0 && r2 < 0 && r3 < 0) {
		return 1;
	}
	return -1;
}

int main(void) {
	int n, flag1, flag2;

	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < 5; j++) {
			cin >> PointData[j].x >> PointData[j].y;
		}
		
		flag1 = isExistTriangle(PointData[3]);
		flag2 = isExistTriangle(PointData[4]);
		//cout << flag1 << ends << flag2 << endl;
		if (flag1*flag2 == 1) {
			cout << "NG" << endl;
		}
		else {
			cout << "OK" << endl;
		}
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3080
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;

class Point {
public:
	int x, y;
};

Point PointData[5];


int isExistTriangle(const Point& p) {

	int r1 = (PointData[1].x - PointData[0].x) * (p.y - PointData[0].y) - (p.x - PointData[0].x) * (PointData[1].y - PointData[0].y);
	int r2 = (PointData[2].x - PointData[1].x) * (p.y - PointData[1].y) - (p.x - PointData[1].x) * (PointData[2].y - PointData[1].y);
	int r3 = (PointData[0].x - PointData[2].x) * (p.y - PointData[2].y) - (p.x - PointData[2].x) * (PointData[0].y - PointData[2].y);

	if (r1 >= 0 && r2 >= 0 && r3 >= 0) {
		return 1;
	}
	if (r1 <= 0 && r2 <= 0 && r3 <= 0) {
		return 1;
	}
	return -1;
}

int main(void) {
	int n, flag1, flag2;

	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < 5; j++) {
			cin >> PointData[j].x >> PointData[j].y;
		}
		
		flag1 = isExistTriangle(PointData[3]);
		flag2 = isExistTriangle(PointData[4]);
		//cout << flag1 << ends << flag2 << endl;
		if (flag1*flag2 == 1) {
			cout << "NG" << endl;
		}
		else {
			cout << "OK" << endl;
		}
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3080
final_rank: 6

code_snippet: #include <iostream>
#include <queue>
#include <vector>
#include <iostream>
#include <vector>
#include <string>
#include <cassert>
#include <algorithm>
#include <functional>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <deque>
#include <map>
#include <iomanip>
#include <utility>
#include <stack>
using ll = long long;
using ld = long double;
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define all(x) (x).begin(),(x).end()
#define rep3(var, min, max) for (ll (var) = (min); (var) < (max); ++(var))
#define repi3(var, min, max) for (ll (var) = (max) - 1; (var) + 1 > (min); --(var))
#define Mp(a,b) make_pair((a),(b))
#define F first
#define S second
#define Icin(s) ll (s);cin>>(s);
#define Scin(s) ll (s);cin>>(s);
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
const double EPS=1e-10;
double add(double l, double r){
    if(abs(l+r)<EPS*(abs(l)+abs(r))) return 0;
    return l+r;
}
//l-r は add(l,-r)
//l==r は add(l,-r)==0
struct Pt{
    double x, y;
    Pt(double xx=0, double yy=0){x=xx; y=yy;}
    Pt& operator=(const Pt &rhs){
        x=rhs.x; y=rhs.y; return *this;
    }
    Pt& operator+=(const Pt &rhs){
        x = add(x,rhs.x); y = add(y,rhs.y); return *this;
    }
    Pt& operator-=(const Pt &rhs){
        x = add(x,-rhs.x); y = add(y,-rhs.y); return *this;
    }
    Pt& operator*=(const double &rhs){
        x *= rhs; y *= rhs; return *this;
    }
    Pt& operator/=(const double &rhs){
        x /= rhs; y /= rhs; return *this;
    }
};
Pt operator+(const Pt &a){return a;}
Pt operator-(const Pt &a){return Pt(-a.x,-a.y);}
Pt operator+(const Pt &lhs, const Pt &rhs){
    Pt ans=lhs; ans += rhs; return ans;
}
Pt operator-(const Pt &lhs, const Pt &rhs){
    Pt ans=lhs; ans -= rhs; return ans;
}
Pt operator*(const Pt &lhs, const double &rhs){
    Pt ans=lhs; ans *= rhs; return ans;
}
Pt operator*(const double &lhs, const Pt &rhs){
    Pt ans=rhs; ans *= lhs; return ans;
}
Pt operator/(const Pt &lhs, const double &rhs){
    Pt ans=lhs; ans /= rhs; return ans;
}
bool operator==(const Pt &lhs, const Pt &rhs){
    return add(lhs.x,-rhs.x)==0 && add(lhs.y,-rhs.y)==0;
}
bool operator!=(const Pt &lhs, const Pt &rhs){return !(lhs==rhs);}
bool operator<(const Pt &lhs, const Pt &rhs){
    return add(lhs.x,-rhs.x)!=0 ? lhs.x<rhs.x : add(lhs.y,-rhs.y)<0;
}
bool operator>(const Pt &lhs, const Pt &rhs){return rhs<lhs;}
bool operator<=(const Pt &lhs, const Pt &rhs){return !(lhs>rhs);}
bool operator>=(const Pt &lhs, const Pt &rhs){return !(lhs<rhs);}
istream& operator>>(istream &is, Pt &rhs){
    double x, y;
    is >> x >> y;
    rhs=Pt(x,y);
    return is;
}
ostream& operator<<(ostream &os, const Pt &rhs){
    os << rhs.x << " " << rhs.y;
    return os;
}
double norm(const Pt &a){return add(a.x*a.x,a.y*a.y);}
double abs(const Pt &a){return sqrt(norm(a));}
double dot(Pt a, Pt b){return add(a.x*b.x,a.y*b.y);}
double cross(Pt a, Pt b){return add(a.x*b.y,-a.y*b.x);}
int ccw(Pt a, Pt b, Pt c) {
    b -= a; c -= a;
    if(cross(b, c)>0) return +2;  // counter clockwise
    if(cross(b, c)<0) return -2;  // clockwise
    if(dot(b, c)<0) return +1;        // c--a--b on line
    if(norm(c)<norm(b)) return -1;    // b--c--a on line
    return 0;                         // a--b--c on line
}
bool judge_cross(ld ax,ld ay,ld bx,ld by,ld cx,ld cy,ld dx,ld dy){
    ld ta = (cx - dx) * (ay - cy) + (cy - dy) * (cx - ax);
    ld tb = (cx - dx) * (by - cy) + (cy - dy) * (cx - bx);
    ld tc = (ax - bx) * (cy - ay) + (ay - by) * (ax - cx);
    ld td = (ax - bx) * (dy - ay) + (ay - by) * (ax - dx);

  return tc * td < 0 && ta * tb < 0;
}
int main(){
    int n;
    cin>>n;
    rep(i,n){
        vector<Pt> vec(3);
        rep(j,3)cin>>vec[j];
        ld xk,yk,xs,ys;
        cin>>xk>>yk>>xs>>ys;
        int c=0;
        if(judge_cross(vec[0].x,vec[0].y,vec[1].x,vec[1].y,xk,yk,xs,ys))c++;
        if(judge_cross(vec[1].x,vec[1].y,vec[2].x,vec[2].y,xk,yk,xs,ys))c++;
        if(judge_cross(vec[2].x,vec[2].y,vec[0].x,vec[0].y,xk,yk,xs,ys))c++;
       //cout<<c<<endl;
        if(c==0||c==2){
            cout<<"NG"<<endl;
        }else{
            cout<<"OK"<<endl;
        }
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3144
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define int long long
// #define double long double
#define FOR(i, a, b) for(ll i = (a); i < (b); ++i)
#define FORR(i, a, b) for(ll i = (a); i > (b); --i)
#define REP(i, n) for(ll i = 0; i < (n); ++i)
#define REPR(i, n) for(ll i = n; i >= 0; i--)
#define FOREACH(x, a) for(auto &(x) : (a))
#define VECCIN(x)                                                              \
    for(auto &youso_ : (x)) cin >> youso_
#define bitcnt __builtin_popcount
#define SZ(x) ((ll)(x).size())
#define fi first
#define se second
#define All(a) (a).begin(), (a).end()
#define rAll(a) (a).rbegin(), (a).rend()
template <typename T = long long> inline T IN() {
    T x;
    cin >> x;
    return (x);
}
inline void CIN() {}
template <class Head, class... Tail>
inline void CIN(Head &&head, Tail &&... tail) {
    cin >> head;
    CIN(move(tail)...);
}
#define CCIN(...)                                                              \
    char __VA_ARGS__;                                                          \
    CIN(__VA_ARGS__)
#define DCIN(...)                                                              \
    double __VA_ARGS__;                                                        \
    CIN(__VA_ARGS__)
#define LCIN(...)                                                              \
    ll __VA_ARGS__;                                                            \
    CIN(__VA_ARGS__)
#define SCIN(...)                                                              \
    string __VA_ARGS__;                                                        \
    CIN(__VA_ARGS__)
#define Printv(v)                                                              \
    {                                                                          \
        REP(x, v.size()) { cout << v[x] << (x == v.size() - 1 ? "\n" : " "); } \
    }
template <typename T = string> inline void eputs(T s) {
    cout << s << "\n";
    exit(0);
}
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
    std::fill((T *)array, (T *)(array + N), val);
}
template <typename T> using PQG = priority_queue<T, vector<T>, greater<T>>;
template <typename T> using PQ = priority_queue<T>;

typedef long long ll;
typedef pair<ll, ll> PL;
typedef vector<PL> VPL;
typedef vector<ll> VL;
typedef vector<VL> VVL;
typedef vector<double> VD;

const int INF = 1e9;
const int MOD = 1e9 + 7;
const ll LINF = 1e18;
const ll dx[] = {1, 0, -1, 0};
const ll dy[] = {0, 1, 0, -1};

#define EPS (1e-10)
#define equals(a, b) (fabs((a) - (b)) < EPS)
#define PI 3.141592653589793238

// COUNTER CLOCKWISE
static const int CCW_COUNTER_CLOCKWISE = 1;
static const int CCW_CLOCKWISE = -1;
static const int CCW_ONLINE_BACK = 2;
static const int CCW_ONLINE_FRONT = -2;
static const int CCW_ON_SEGMENT = 0;

// Intercsect Circle & Circle
static const int ICC_SEPERATE = 4;
static const int ICC_CIRCUMSCRIBE = 3;
static const int ICC_INTERSECT = 2;
static const int ICC_INSCRIBE = 1;
static const int ICC_CONTAIN = 0;

struct Point {
    double x, y;
    Point() {}
    Point(double x, double y) : x(x), y(y) {}
    Point operator+(Point p) { return Point(x + p.x, y + p.y); }
    Point operator-(Point p) { return Point(x - p.x, y - p.y); }
    Point operator*(double k) { return Point(x * k, y * k); }
    Point operator/(double k) { return Point(x / k, y / k); }
    double norm() { return x * x + y * y; }
    double abs() { return sqrt(norm()); }

    bool operator<(const Point &p) const {
        return x != p.x ? x < p.x : y < p.y;
        // grid-point only
        // return !equals(x,p.x)?x<p.x:!equals(y,p.y)?y<p.y:0;
    }

    bool operator==(const Point &p) const {
        return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
    }
};

struct EndPoint {
    Point p;
    int seg, st;
    EndPoint() {}
    EndPoint(Point p, int seg, int st) : p(p), seg(seg), st(st) {}
    bool operator<(const EndPoint &ep) const {
        if(p.y == ep.p.y) return st < ep.st;
        return p.y < ep.p.y;
    }
};

istream &operator>>(istream &is, Point &p) {
    is >> p.x >> p.y;
    return is;
}

ostream &operator<<(ostream &os, Point p) {
    os << fixed << setprecision(12) << p.x << " " << p.y;
    return os;
}

bool sort_x(Point a, Point b) { return a.x != b.x ? a.x < b.x : a.y < b.y; }

bool sort_y(Point a, Point b) { return a.y != b.y ? a.y < b.y : a.x < b.x; }

typedef Point Vector;
typedef vector<Point> Polygon;

istream &operator>>(istream &is, Polygon &p) {
    for(int i = 0; i < (int)p.size(); i++) is >> p[i];
    return is;
}

struct Segment {
    Point p1, p2;
    Segment() {}
    Segment(Point p1, Point p2) : p1(p1), p2(p2) {}
};
typedef Segment Line;

istream &operator>>(istream &is, Segment &s) {
    is >> s.p1 >> s.p2;
    return is;
}

struct Circle {
    Point c;
    double r;
    Circle() {}
    Circle(Point c, double r) : c(c), r(r) {}
};

istream &operator>>(istream &is, Circle &c) {
    is >> c.c >> c.r;
    return is;
}

double norm(Vector a) { return a.x * a.x + a.y * a.y; }
double abs(Vector a) { return sqrt(norm(a)); }
double dot(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }
double cross(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }

Point orth(Point p) { return Point(-p.y, p.x); }

bool isOrthogonal(Vector a, Vector b) { return equals(dot(a, b), 0.0); }

bool isOrthogonal(Point a1, Point a2, Point b1, Point b2) {
    return isOrthogonal(a1 - a2, b1 - b2);
}

bool isOrthogonal(Segment s1, Segment s2) {
    return equals(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

bool isParallel(Vector a, Vector b) { return equals(cross(a, b), 0.0); }

bool isParallel(Point a1, Point a2, Point b1, Point b2) {
    return isParallel(a1 - a2, b1 - b2);
}

bool isParallel(Segment s1, Segment s2) {
    return equals(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

Point project(Segment s, Point p) {
    Vector base = s.p2 - s.p1;
    double r = dot(p - s.p1, base) / norm(base);
    return s.p1 + base * r;
}

Point reflect(Segment s, Point p) { return p + (project(s, p) - p) * 2.0; }

double arg(Vector p) { return atan2(p.y, p.x); }

Vector polar(double a, double r) { return Point(cos(r) * a, sin(r) * a); }

int ccw(Point p0, Point p1, Point p2);
bool intersectSS(Point p1, Point p2, Point p3, Point p4);
bool intersectSS(Segment s1, Segment s2);
bool intersectPS(Polygon p, Segment l);
int intersectCC(Circle c1, Circle c2);
bool intersectSC(Segment s, Circle c);
double getDistanceLP(Line l, Point p);
double getDistanceSP(Segment s, Point p);
double getDistanceSS(Segment s1, Segment s2);
Point getCrossPointSS(Segment s1, Segment s2);
Point getCrossPointLL(Line l1, Line l2);
Polygon getCrossPointCL(Circle c, Line l);
Polygon getCrossPointCC(Circle c1, Circle c2);
int contains(Polygon g, Point p);
Polygon andrewScan(Polygon s);
Polygon convex_hull(Polygon ps);
double diameter(Polygon s);
bool isConvex(Polygon p);
double area(Polygon s);
Polygon convexCut(Polygon p, Line l);
Line bisector(Point p1, Point p2);
Vector translate(Vector v, double theta);
vector<Line> corner(Line l1, Line l2);
vector<vector<int>> segmentArrangement(vector<Segment> &ss, Polygon &ps);

int ccw(Point p0, Point p1, Point p2) {
    Vector a = p1 - p0;
    Vector b = p2 - p0;
    if(cross(a, b) > EPS) return CCW_COUNTER_CLOCKWISE;
    if(cross(a, b) < -EPS) return CCW_CLOCKWISE;
    if(dot(a, b) < -EPS) return CCW_ONLINE_BACK;
    if(a.norm() < b.norm()) return CCW_ONLINE_FRONT;
    return CCW_ON_SEGMENT;
}

bool intersectSS(Point p1, Point p2, Point p3, Point p4) {
    return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
            ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}

bool intersectSS(Segment s1, Segment s2) {
    return intersectSS(s1.p1, s1.p2, s2.p1, s2.p2);
}

bool intersectPS(Polygon p, Segment l) {
    int n = p.size();
    for(int i = 0; i < n; i++)
        if(intersectSS(Segment(p[i], p[(i + 1) % n]), l)) return 1;
    return 0;
}

int intersectCC(Circle c1, Circle c2) {
    if(c1.r < c2.r) swap(c1, c2);
    double d = abs(c1.c - c2.c);
    double r = c1.r + c2.r;
    if(equals(d, r)) return ICC_CIRCUMSCRIBE;
    if(d > r) return ICC_SEPERATE;
    if(equals(d + c2.r, c1.r)) return ICC_INSCRIBE;
    if(d + c2.r < c1.r) return ICC_CONTAIN;
    return ICC_INTERSECT;
}

bool intersectSC(Segment s, Circle c) { return getDistanceSP(s, c.c) <= c.r; }

int intersectCS(Circle c, Segment s) {
    if(norm(project(s, c.c) - c.c) - c.r * c.r > EPS) return 0;
    double d1 = abs(c.c - s.p1), d2 = abs(c.c - s.p2);
    if(d1 < c.r + EPS && d2 < c.r + EPS) return 0;
    if((d1 < c.r - EPS && d2 > c.r + EPS) || (d1 > c.r + EPS && d2 < c.r - EPS))
        return 1;
    Point h = project(s, c.c);
    if(dot(s.p1 - h, s.p2 - h) < 0) return 2;
    return 0;
}

double getDistanceLP(Line l, Point p) {
    return abs(cross(l.p2 - l.p1, p - l.p1) / abs(l.p2 - l.p1));
}

double getDistanceSP(Segment s, Point p) {
    if(dot(s.p2 - s.p1, p - s.p1) < 0.0) return abs(p - s.p1);
    if(dot(s.p1 - s.p2, p - s.p2) < 0.0) return abs(p - s.p2);
    return getDistanceLP(s, p);
}

double getDistanceSS(Segment s1, Segment s2) {
    if(intersectSS(s1, s2)) return 0.0;
    return min(min(getDistanceSP(s1, s2.p1), getDistanceSP(s1, s2.p2)),
               min(getDistanceSP(s2, s1.p1), getDistanceSP(s2, s1.p2)));
}

Point getCrossPointSS(Segment s1, Segment s2) {
    for(int k = 0; k < 2; k++) {
        if(getDistanceSP(s1, s2.p1) < EPS) return s2.p1;
        if(getDistanceSP(s1, s2.p2) < EPS) return s2.p2;
        swap(s1, s2);
    }
    Vector base = s2.p2 - s2.p1;
    double d1 = abs(cross(base, s1.p1 - s2.p1));
    double d2 = abs(cross(base, s1.p2 - s2.p1));
    double t = d1 / (d1 + d2);
    return s1.p1 + (s1.p2 - s1.p1) * t;
}

Point getCrossPointLL(Line l1, Line l2) {
    double a = cross(l1.p2 - l1.p1, l2.p2 - l2.p1);
    double b = cross(l1.p2 - l1.p1, l1.p2 - l2.p1);
    if(abs(a) < EPS && abs(b) < EPS) return l2.p1;
    return l2.p1 + (l2.p2 - l2.p1) * (b / a);
}

Polygon getCrossPointCL(Circle c, Line l) {
    Polygon ps;
    Point pr = project(l, c.c);
    Vector e = (l.p2 - l.p1) / abs(l.p2 - l.p1);
    if(equals(getDistanceLP(l, c.c), c.r)) {
        ps.emplace_back(pr);
        return ps;
    }
    double base = sqrt(c.r * c.r - norm(pr - c.c));
    ps.emplace_back(pr + e * base);
    ps.emplace_back(pr - e * base);
    return ps;
}

Polygon getCrossPointCS(Circle c, Segment s) {
    Line l(s);
    Polygon res = getCrossPointCL(c, l);
    if(intersectCS(c, s) == 2) return res;
    if(res.size() > 1u) {
        if(dot(l.p1 - res[0], l.p2 - res[0]) > 0) swap(res[0], res[1]);
        res.pop_back();
    }
    return res;
}

Polygon getCrossPointCC(Circle c1, Circle c2) {
    Polygon p(2);
    double d = abs(c1.c - c2.c);
    double a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    double t = arg(c2.c - c1.c);
    p[0] = c1.c + polar(c1.r, t + a);
    p[1] = c1.c + polar(c1.r, t - a);
    return p;
}

// IN:2 ON:1 OUT:0
int contains(Polygon g, Point p) {
    int n = g.size();
    bool x = false;
    for(int i = 0; i < n; i++) {
        Point a = g[i] - p, b = g[(i + 1) % n] - p;
        if(fabs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
        if(a.y > b.y) swap(a, b);
        if(a.y < EPS && EPS < b.y && cross(a, b) > EPS) x = !x;
    }
    return (x ? 2 : 0);
}

Polygon andrewScan(Polygon s) {
    Polygon u, l;
    if(s.size() < 3) return s;
    sort(s.begin(), s.end());
    u.push_back(s[0]);
    u.push_back(s[1]);
    l.push_back(s[s.size() - 1]);
    l.push_back(s[s.size() - 2]);
    for(int i = 2; i < (int)s.size(); i++) {
        for(int n = u.size();
            n >= 2 && ccw(u[n - 2], u[n - 1], s[i]) != CCW_CLOCKWISE; n--) {
            u.pop_back();
        }
        u.push_back(s[i]);
    }
    for(int i = s.size() - 3; i >= 0; i--) {
        for(int n = l.size();
            n >= 2 && ccw(l[n - 2], l[n - 1], s[i]) != CCW_CLOCKWISE; n--) {
            l.pop_back();
        }
        l.push_back(s[i]);
    }
    reverse(l.begin(), l.end());
    for(int i = u.size() - 2; i >= 1; i--) l.push_back(u[i]);
    return l;
}

Polygon convex_hull(Polygon ps) {
    int n = ps.size();
    sort(ps.begin(), ps.end(), sort_y);
    int k = 0;
    Polygon qs(n * 2);
    for(int i = 0; i < n; i++) {
        while(k > 1 && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < 0) k--;
        qs[k++] = ps[i];
    }
    for(int i = n - 2, t = k; i >= 0; i--) {
        while(k > t && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < 0) k--;
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}

double diameter(Polygon s) {
    Polygon p = s;
    int n = p.size();
    if(n == 2) return abs(p[0] - p[1]);
    int i = 0, j = 0;
    for(int k = 0; k < n; k++) {
        if(p[i] < p[k]) i = k;
        if(!(p[j] < p[k])) j = k;
    }
    double res = 0;
    int si = i, sj = j;
    while(i != sj || j != si) {
        res = max(res, abs(p[i] - p[j]));
        if(cross(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j]) < 0.0) {
            i = (i + 1) % n;
        } else {
            j = (j + 1) % n;
        }
    }
    return res;
}

bool isConvex(Polygon p) {
    bool f = 1;
    int n = p.size();
    for(int i = 0; i < n; i++) {
        int t = ccw(p[(i + n - 1) % n], p[i], p[(i + 1) % n]);
        f &= t != CCW_CLOCKWISE;
    }
    return f;
}

double area(Polygon s) {
    double res = 0;
    for(int i = 0; i < (int)s.size(); i++) {
        res += cross(s[i], s[(i + 1) % s.size()]) / 2.0;
    }
    return res;
}

double area(Circle c1, Circle c2) {
    double d = abs(c1.c - c2.c);
    if(c1.r + c2.r <= d + EPS) return 0;
    if(d <= abs(c1.r - c2.r)) {
        double r = min(c1.r, c2.r);
        return PI * r * r;
    }
    double rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
    double th = acos(rc / c1.r);
    double ph = acos((d - rc) / c2.r);
    return c1.r * c1.r * th + c2.r * c2.r * ph - d * c1.r * sin(th);
}

Polygon convexCut(Polygon p, Line l) {
    Polygon q;
    for(int i = 0; i < (int)p.size(); i++) {
        Point a = p[i], b = p[(i + 1) % p.size()];
        if(ccw(l.p1, l.p2, a) != -1) q.push_back(a);
        if(ccw(l.p1, l.p2, a) * ccw(l.p1, l.p2, b) < 0)
            q.push_back(getCrossPointLL(Line(a, b), l));
    }
    return q;
}

Line bisector(Point p1, Point p2) {
    Circle c1 = Circle(p1, abs(p1 - p2)), c2 = Circle(p2, abs(p1 - p2));
    Polygon p = getCrossPointCC(c1, c2);
    if(cross(p2 - p1, p[0] - p1) > 0) swap(p[0], p[1]);
    return Line(p[0], p[1]);
}

Vector translate(Vector v, double theta) {
    Vector res;
    res.x = cos(theta) * v.x - sin(theta) * v.y;
    res.y = sin(theta) * v.x + cos(theta) * v.y;
    return res;
}

vector<Line> corner(Line l1, Line l2) {
    vector<Line> res;
    if(isParallel(l1, l2)) {
        double d = getDistanceLP(l1, l2.p1) / 2.0;
        Vector v1 = l1.p2 - l1.p1;
        v1 = v1 / v1.abs() * d;
        Point p = l2.p1 + translate(v1, 90.0 * (PI / 180.0));
        double d1 = getDistanceLP(l1, p);
        double d2 = getDistanceLP(l2, p);
        if(abs(d1 - d2) > d) {
            p = l2.p1 + translate(v1, -90.0 * (PI / 180.0));
        }
        res.push_back(Line(p, p + v1));
    } else {
        Point p = getCrossPointLL(l1, l2);
        Vector v1 = l1.p2 - l1.p1, v2 = l2.p2 - l2.p1;
        v1 = v1 / v1.abs();
        v2 = v2 / v2.abs();
        res.push_back(Line(p, p + (v1 + v2)));
        res.push_back(Line(p, p + translate(v1 + v2, 90.0 * (PI / 180.0))));
    }
    return res;
}

Polygon tangent(Circle c1, Point p2) {
    Circle c2 = Circle(p2, sqrt(norm(c1.c - p2) - c1.r * c1.r));
    Polygon p = getCrossPointCC(c1, c2);
    sort(p.begin(), p.end());
    return p;
}

vector<Line> tangent(Circle c1, Circle c2) {
    vector<Line> ls;
    if(c1.r < c2.r) swap(c1, c2);
    double g = norm(c1.c - c2.c);
    if(equals(g, 0)) return ls;
    Point u = (c2.c - c1.c) / sqrt(g);
    Point v = orth(u);
    for(int s = 1; s >= -1; s -= 2) {
        double h = (c1.r + s * c2.r) / sqrt(g);
        if(equals(1 - h * h, 0)) {
            ls.emplace_back(c1.c + u * c1.r, c1.c + (u + v) * c1.r);
        } else if(1 - h * h > 0) {
            Point uu = u * h, vv = v * sqrt(1 - h * h);
            ls.emplace_back(c1.c + (uu + vv) * c1.r,
                            c2.c - (uu + vv) * c2.r * s);
            ls.emplace_back(c1.c + (uu - vv) * c1.r,
                            c2.c - (uu - vv) * c2.r * s);
        }
    }

    return ls;
}

double closest_pair(Polygon &a, int l = 0, int r = -1) {
    if(r < 0) {
        r = a.size();
        sort(a.begin(), a.end(), sort_x);
    }
    if(r - l <= 1) return abs(a[0] - a[1]);
    int m = (l + r) >> 1;
    double x = a[m].x;
    double d = min(closest_pair(a, l, m), closest_pair(a, m, r));
    inplace_merge(a.begin() + l, a.begin() + m, a.begin() + r, sort_y);

    Polygon b;
    for(int i = l; i < r; i++) {
        if(fabs(a[i].x - x) >= d) continue;
        for(int j = 0; j < (int)b.size(); j++) {
            double dy = a[i].y - next(b.rbegin(), j)->y;
            if(dy >= d) break;
            d = min(d, abs(a[i] - *next(b.rbegin(), j)));
        }
        b.emplace_back(a[i]);
    }
    return d;
}

vector<vector<int>> segmentArrangement(vector<Segment> &ss, Polygon &ps) {
    int n = ss.size();
    for(int i = 0; i < n; i++) {
        ps.emplace_back(ss[i].p1);
        ps.emplace_back(ss[i].p2);
        for(int j = i + 1; j < n; j++)
            if(intersectSS(ss[i], ss[j]))
                ps.emplace_back(getCrossPointSS(ss[i], ss[j]));
    }
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());

    vector<vector<int>> G(ps.size());
    for(int i = 0; i < n; i++) {
        vector<pair<double, int>> ls;
        for(int j = 0; j < (int)ps.size(); j++)
            if(getDistanceSP(ss[i], ps[j]) < EPS)
                ls.emplace_back(make_pair(norm(ss[i].p1 - ps[j]), j));

        sort(ls.begin(), ls.end());
        for(int j = 0; j + 1 < (int)ls.size(); j++) {
            int a = ls[j].second, b = ls[j + 1].second;
            G[a].emplace_back(b);
            G[b].emplace_back(a);
        }
    }
    for(auto &v : G) {
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    }
    return G;
}

int manhattanIntersection(vector<Segment> ss, const int INF) {
    const int BTM = 0;
    const int LFT = 1;
    const int RGH = 2;
    const int TOP = 3;

    int n = ss.size();
    vector<EndPoint> ep;
    for(int i = 0; i < n; i++) {
        if(ss[i].p1.y == ss[i].p2.y) {
            if(ss[i].p1.x > ss[i].p2.x) swap(ss[i].p1, ss[i].p2);
            ep.emplace_back(ss[i].p1, i, LFT);
            ep.emplace_back(ss[i].p2, i, RGH);
        } else {
            if(ss[i].p1.y > ss[i].p2.y) swap(ss[i].p1, ss[i].p2);
            ep.emplace_back(ss[i].p1, i, BTM);
            ep.emplace_back(ss[i].p2, i, TOP);
        }
    }
    sort(ep.begin(), ep.end());

    set<int> bt;
    bt.insert(INF);

    int cnt = 0;
    for(int i = 0; i < n * 2; i++) {
        if(ep[i].st == TOP) {
            bt.erase(ep[i].p.x);
        } else if(ep[i].st == BTM) {
            bt.emplace(ep[i].p.x);
        } else if(ep[i].st == LFT) {
            auto b = bt.lower_bound(ss[ep[i].seg].p1.x);
            auto e = bt.upper_bound(ss[ep[i].seg].p2.x);
            cnt += distance(b, e);
        }
    }

    return cnt;
}

double area(Polygon ps, Circle c) {
    if(ps.size() < 3u) return 0;
    function<double(Circle, Point, Point)> dfs = [&](Circle c, Point a,
                                                     Point b) {
        Vector va = c.c - a, vb = c.c - b;
        double f = cross(va, vb), res = 0;
        if(equals(f, 0.0)) return res;
        if(max(abs(va), abs(vb)) < c.r + EPS) return f;
        Vector d(dot(va, vb), cross(va, vb));
        if(getDistanceSP(Segment(a, b), c.c) > c.r - EPS)
            return c.r * c.r * atan2(d.y, d.x);
        auto u = getCrossPointCS(c, Segment(a, b));
        if(u.empty()) return res;
        if(u.size() > 1u && dot(u[1] - u[0], a - u[0]) > 0) swap(u[0], u[1]);
        u.emplace(u.begin(), a);
        u.emplace_back(b);
        for(int i = 1; i < (int)u.size(); i++) res += dfs(c, u[i - 1], u[i]);
        return res;
    };
    double res = 0;
    for(int i = 0; i < (int)ps.size(); i++)
        res += dfs(c, ps[i], ps[(i + 1) % ps.size()]);
    return res / 2;
}

signed main() {
    LCIN(N);
    while(N--) {
        DCIN(x1, y1, x2, y2, x3, y3, xk, yk, xs, ys);
        ll cnt = 0;
        cnt += intersectSS(Point(x1, y1), Point(x2, y2), Point(xk, yk),
                           Point(xs, ys));
        cnt += intersectSS(Point(x2, y2), Point(x3, y3), Point(xk, yk),
                           Point(xs, ys));
        cnt += intersectSS(Point(x3, y3), Point(x1, y1), Point(xk, yk),
                           Point(xs, ys));
        cout << (cnt == 1 ? "OK" : "NG") << "\n";
    }
}
accuracy: 1
time_ms: 30
memory_kb: 3176
final_rank: 19