Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

#### Code mẫu của happyboy99x

#include<complex>
#include<vector>
#include<algorithm>
#include<climits>
#include<cmath>
#include<iostream>
using namespace std;

#define TR(v,i) for(__typeof((v).begin())i=(v).begin();i!=(v).end();++i)
#define TRR(v,i) for(__typeof((v).rbegin())i=(v).rbegin();i!=(v).rend();++i)
typedef complex<long long> Point;

long long cross(const Point &a, const Point &b) {
return (conj(a) * b).imag();
}

bool cmp(const Point &a, const Point &b) {
return a.real() == b.real() ? a.imag() < b.imag() : a.real() < b.real();
}

vector<Point> convexhull(vector<Point> &p) {
sort(p.begin(), p.end(), cmp);
vector<Point> hull; int k = 0;
TR(p, it) {
while(k > 1 && cross(hull[k-1]-hull[k-2], *it-hull[k-2]) <= 0)
hull.pop_back(), --k;
hull.push_back(*it); ++k;
}
int t = k; TRR(p, it) {
while(k > t && cross(hull[k-1]-hull[k-2], *it-hull[k-2]) <= 0)
hull.pop_back(), --k;
hull.push_back(*it); ++k;
}
return hull;
}

long long maxdist(const vector<Point> &p, const vector<Point> &q) {
long long res = 0;
TR(p, i) TR(q, j) res = max(res, norm(*j - *i));
return res;
}

vector<Point> p[2];

void enter() {
p[0].clear(); p[1].clear();
int n; cin >> n;
for(int i = 0; i < n; ++i) {
int a, b, c; cin >> a >> b >> c;
p[c].push_back(Point(a, b));
}
}

int main() {
ios::sync_with_stdio(false);
int tc; cin >> tc;
while(tc--) {
enter();
cout << (int) sqrt(maxdist(convexhull(p[0]), convexhull(p[1]))) << endl;
}
return 0;
}


#include <iostream>
#include <cstdio>
#include <iomanip>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <climits>
#include <numeric>
#include <vector>
#include <queue>
#include <map>
#include <utility>
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define REP(i, a, b) for(int i = (a); i <=(b); i++)
#define FORD(i, a, b) for(int i = (a); i > (b); i--)
#define REPD(i, a, b) for(int i = (a); i >=(b); i--)
#define SZ(a) (int((a).size()))
#define ALL(a) (a).begin(), a.end()
#define PB push_back
#define MP make_pair
#define LL long long
#define LD long double
#define II pair<int, int>
#define X first
#define Y second
#define VI vector<int>
#define VII vector<II>
using namespace std;

void operator -= (II &a, II b) {a.X -= b.X; a.Y -= b.Y;}
bool ccw(II a, II b, II c) {c -= b; b -= a; return (LL)b.X * c.Y > (LL)b.Y * c.X;}

void refine(VII &a) {
VII hull;
sort(ALL(a));
#define S hull.size()
FOR(i, 0, SZ(a)) {
while (S > 1 && ccw(hull[S - 2], hull[S - 1], a[i])) hull.pop_back();
hull.PB(a[i]);
}
int t = S;
REPD(i, SZ(a) - 2, 0) {
while (S > t && ccw(hull[S - 2], hull[S - 1], a[i])) hull.pop_back();
hull.PB(a[i]);
}
a = hull;
}

LL dist(II a, II b)
{return (LL)(a.X - b.X) * (a.X - b.X) + (LL)(a.Y - b.Y) * (a.Y - b.Y);}

int main() {
ios :: sync_with_stdio(0); cin.tie(0);
int ntest, n, x, y, c;
cin >> ntest;
while (ntest--) {
cin >> n;
VII poly[2];
FOR(i, 0, n) {
cin >> x >> y >> c;
poly[c].PB(MP(x, y));
}
FOR(i, 0, 2) refine(poly[i]);
LL ans = 0;
FOR(i, 0, SZ(poly[0]))
FOR(j, 0, SZ(poly[1]))
ans = max(ans, dist(poly[0][i], poly[1][j]));
int d = int(sqrt(ans));
if (d * d > ans) cout << d - 1 << '\n';
else cout << d << '\n';
}
return 0;
}


#### Code mẫu của RR

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstdio>

#define FOR(i,a,b) for(int i=(a),_b=(b); i <= _b; ++i)
#define FR(i,a) for(int i=0,_a=(a); i < _a; ++i)
using namespace std;

const double eps = 1e-10;
int cmp(double q,double w) {
return (q < w + eps) ? (q > w - eps) ? 0 : -1 : 1;
}
struct point {
double x,y;
point (double x,double y): x(x),y(y) {}
point () {x=y=0.0; }
point operator +(point q) { return point(x+q.x,y+q.y); }
point operator -(point q) { return point(x-q.x,y-q.y); }
point operator *(double t) { return point(x*t,y*t); }
point operator /(double t) { return point(x/t,y/t); }
double operator *(point q){ return q.x * x + q.y * y; }
double operator %(point q){ return x*q.y - y*q.x; }
int cmp(point q) const { if(int t = ::cmp(x,q.x)) return t; return ::cmp(y,q.y); }
#define Comp(x) bool operator x (point q) const { return cmp(q) x 0; }
Comp(>) Comp(<) Comp(==) Comp(>=) Comp(<=) Comp(!=)
#undef Comp

double sqlen() { return x*x + y*y; }
};
typedef vector<point> polygon;
inline int ccw(point a, point b, point c) {
return cmp((b-a)%(c-a),0);
}
double area(polygon &p) {
double s = 0.0;
FOR(i,1,(int)p.size()-1) s+= (p[i]-p[0])%(p[(i+1)%p.size()]-p[0]);
return fabs(s) / 2.0;
}
struct comp_hull {
point pivot;
bool operator() (point q,point w) {
point Q = q - pivot, W = w - pivot;
double R = Q % W;
if (cmp(R,0)) return R < 0;
return cmp(Q*Q,W*W) < 0;
}
};
polygon convex_hull(polygon p) { // minimum vertices
int j = 0, k, n = p.size();
polygon r(n);
if (!n) return r;
comp_hull comp;
comp.pivot = *min_element(p.begin(),p.end());
sort(p.begin(),p.end(),comp);
FR(i,n) {
while (j > 1 && ccw(r[j-1],r[j-2],p[i]) <= 0) j--;
r[j++] = p[i];
}
r.resize(j);
return r;
}

const int MN = 30111;
int x[MN], y[MN], t[MN];

int main() {
int ntest; scanf("%d", &ntest);
while (ntest--) {
polygon a, b;
int n; scanf("%d", &n);
FOR(i,1,n) {
scanf("%d%d%d", &x[i], &y[i], &t[i]);
if (t[i] == 0) a.push_back(point(x[i], y[i]));
else b.push_back(point(x[i], y[i]));
}

a = convex_hull(a); b = convex_hull(b);

double res = -1;
FR(i,a.size()) FR(j,b.size()) {
res = max(res, (a[i] - b[j]).sqlen());
}

printf("%d\n", (int) (sqrt(res) + 1e-6));
}
}


#### Code mẫu của hieult

#include<cstdio>
#include<cmath>
#include<math.h>
#include<cstring>
#include<cstdlib>
#include<cassert>
#include<ctime>
#include<algorithm>
#include<iterator>
#include<iostream>
#include<cctype>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<list>
#define ep 0.00001
#define maxn 30111
#define oo 1111111111
#define modunlo 111539786
#define TR(c, it) for(typeof((c).begin()) it=(c).begin(); it!=(c).end(); it++)
#define g 9.81
double const PI=4*atan(1.0);

using namespace std;

struct Point {
int x, y;
Point() {};
Point(int _x, int _y) {
x = _x;
y = _y;
}
};

Point O;

int ccw(Point A, Point B, Point C) {
long long dx1 = B.x - A.x, dy1 = B.y - A.y;
long long dx2 = C.x - A.x, dy2 = C.y - A.y;
long long ret = dx1 * dy2 - dx2 * dy1;
if (ret == 0) return 0;
return ret < 0 ? -1 : +1;
}

long long sqr(int x) {
return (long long) x * x;
}

long long sqrdist(Point P1, Point P2) {
return sqr(P1.x - P2.x) + sqr(P1.y - P2.y);
}

bool nearer(Point P1, Point P2) {
return sqrdist(O, P1) < sqrdist(O, P2);
}

bool cmp(Point P1, Point P2) {
int c = ccw(O, P1, P2);
if (c != 0) return c > 0;
return nearer(P1, P2);
}

void graham(Point a[], int &n) {
int imin = 0;
for (int i = 1; i < n; ++i) {
if (a[imin].y > a[i].y) imin = i;
else if (a[imin].y == a[i].y && a[imin].x > a[i].x) imin = i;
}

O = a[imin];
swap(a[0], a[imin]);
sort(a + 1, a + n, cmp);

int inow = 1;
for (int i = 2; i < n; ++i) {
while (inow > 0 && ccw(a[i], a[inow], a[inow - 1]) >= 0) --inow;
++inow;
swap(a[inow], a[i]);
}

n = inow + 1;
}

bool cmpYX(Point P1, Point P2) {
if (P1.y != P2.y) return P1.y < P2.y;
return P1.x < P2.x;
}

Point G[maxn],M[maxn];
int test,n,n1,n2,x,y,c;

int main() {
//    freopen("_.in", "r", stdin);
// freopen("output.out", "w", stdout);
scanf("%d",&test);
for(int itest = 0;itest<test;itest++){
scanf("%d",&n);
n1 = 0,n2 = 0;
for(int i = 0;i<n;i++){
scanf("%d %d %d",&x,&y,&c);
if(c){
G[n1++] = Point(x,y);
}
else{
M[n2++] = Point(x,y);
}
}
graham(G,n1);
graham(M,n2);
long long MAX = 0;
for(int i = 0;i<n1;i++) for(int j = 0;j<n2;j++) MAX = max(MAX,sqrdist(G[i],M[j]));
printf("%d\n",int(sqrt(MAX)));
}

return 0;
}


#### Code mẫu của skyvn97

#include<cstdio>
#include<cmath>
#include<algorithm>
#define MAX   30303
#define INF   1e9
using namespace std;
typedef long long ll;
struct point {
ll x,y;
point(){
x=0;y=0;
}
point(const ll &_x,const ll &_y) {
x=_x;y=_y;
}
point operator + (const point &a) const {
return (point(x+a.x,y+a.y));
}
point operator - (const point &a) const {
return (point(x-a.x,y-a.y));
}
ll operator ^ (const point &a) const {
return (x*a.y-a.x*y);
}
bool operator < (const point &a) const {
if (y<a.y) return (true);
if (y>a.y) return (false);
return (x<a.x);
}
};
struct stack {
int size;
point bd[MAX];
stack(){}
void clear(void) {
size=0;
}
void push(const point &v) {
size++;
bd[size]=v;
}
void pop(void) {
size--;
}
bool empty(void) {
return (size==0);
}
point operator [] (const int &i) {
return (bd[i]);
}
};
int ccw(const point &a,const point &b,const point &c) {
ll cp=(b-a)^(c-a);
if (cp==0) return (0);
if (cp<0) return (-1);
if (cp>0) return (1);
}
bool cmp(const point &a,const point &b) {
int t=ccw(point(),a,b);
if (t>0) return (true);
if (t<0) return (false);
return (a.y<b.y);
}
int m,n,p;
point a[MAX];
point b[MAX];
point da,db;
stack ca,cb;
void swap(point &a,point &b) {
point sw;
sw=a;a=b;b=sw;
}
void init(void) {
m=0;n=0;
int i,t;
ll x,y;
scanf("%d",&p);
for (i=1;i<=p;i=i+1) {
scanf("%lld",&x);
scanf("%lld",&y);
scanf("%d",&t);
if (t==0) {
m++;
a[m]=point(x,y);
}
else {
n++;
b[n]=point(x,y);
}
}
}
void convert_hull(const int &m,point a[],point &da,stack &ca) {
da=point(INF,INF);
int i,im;
for (i=1;i<=m;i=i+1)
if (a[i]<da) {
da=a[i];
im=i;
}
swap(a[1],a[im]);
for (i=1;i<=m;i=i+1) a[i]=a[i]-da;
sort(&a[2],&a[m+1],cmp);
ca.clear();
for (i=1;i<=m;i=i+1) {
if (ca.size<2) {
ca.push(a[i]);
}
else {
while (ccw(ca[ca.size-1],ca[ca.size],a[i])<=0 && ca.size>1) ca.pop();
ca.push(a[i]);
}
}
}
ll dis(const point &a,const point &b) {
return (floor(hypot(a.x-b.x,a.y-b.y)));
}
ll max(const ll &x,const ll &y) {
if (x>y) return (x); else return (y);
}
void process(void) {
convert_hull(m,a,da,ca);
convert_hull(n,b,db,cb);
ll res=-1;
int i,j;
for (i=1;i<=ca.size;i=i+1)
for (j=1;j<=cb.size;j=j+1)
res=max(res,dis(ca[i]+da,cb[j]+db));
printf("%lld\n",res);
}
int main(void) {
int t,c;
scanf("%d",&t);
for (c=1;c<=t;c=c+1) {
init();
process();
}
return 0;
}