#include <fstream>
#include <algorithm>
#include <vector>
#define lint long long int
using namespace std;
class InputReader {
public:
InputReader() {}
InputReader(const char *file_name) {
input_file = fopen(file_name, "r");
cursor = 0;
fread(buffer, SIZE, 1, input_file);
}
inline InputReader &operator >>(int &n) {
while(buffer[cursor] < '0' || buffer[cursor] > '9') {
advance();
}
n = 0;
while('0' <= buffer[cursor] && buffer[cursor] <= '9') {
n = n * 10 + buffer[cursor] - '0';
advance();
}
return *this;
}
private:
FILE *input_file;
static const int SIZE = 1 << 17;
int cursor;
char buffer[SIZE];
inline void advance() {
++ cursor;
if(cursor == SIZE) {
cursor = 0;
fread(buffer, SIZE, 1, input_file);
}
}
}cin("metrou4.in");
const int NMAX = 150005;
int n,t;
struct Point {
int x, y;
int ind;
Point(int _x = 0, int _y = 0, int _ind = 0):
x(_x), y(_y), ind(_ind) {}
} points[NMAX];
bool operator<(const Point &a, const Point &b) {
if (a.x != b.x)
return a.x < b.x;
return a.y < b.y;
}
void reflect() {
for (int i = 1; i <= n; ++ i)
points[i].x = -points[i].x;
}
void rotate() {
for (int i = 1; i <= n; ++ i) {
int old_x = points[i].x;
int old_y = points[i].y;
points[i].x = -old_y;
points[i].y = old_x;
}
}
struct Node {
int st, dr;
int best;
int ind_best;
Node(int _st = 0, int _dr = 0, int _best = 0, int _ind_best = 0):
st(_st), dr(_dr), best(_best), ind_best(_ind_best) {}
void add_point(const Point &p) {
if (!ind_best || p.x + p.y > best)
best = p.x + p.y, ind_best = p.ind;
}
} tree[4 * NMAX];
void build(int node, int st, int dr) {
tree[node].st = st, tree[node].dr = dr;
tree[node].best = tree[node].ind_best = 0;
if (st == dr)
return ;
int mid = (st + dr) >> 1;
node<<=1;
build(node, st, mid);
build(node+1, mid + 1, dr);
}
void update(int node, int where, const Point &p) {
tree[node].add_point(p);
if (tree[node].st == tree[node].dr)
return ;
int mid = (tree[node].st + tree[node].dr) >> 1;
node<<=1;
if (where <= mid)
update(node, where, p);
else
update(node + 1, where, p);
}
pair <int, int> query(int node, int where) {
if (tree[node].dr == where)
return make_pair(tree[node].best, tree[node].ind_best);
int mid = (tree[node].st + tree[node].dr) >> 1;
pair <int, int> ans = make_pair(0, 0);
node<<=1;
if (where <= mid)
ans = query(node, where);
else {
pair <int, int> aux = query(node, mid);
if (!ans.second || (aux.second && aux.first > ans.first))
ans = aux;
aux = query(node + 1, where);
if (!ans.second || (aux.second && aux.first > ans.first))
ans = aux;
}
return ans;
}
int father[NMAX];
int h[NMAX];
void init() {
for (int i = 1; i <= n; ++ i)
father[i] = i, h[i] = 0;
}
int find(int node) {
if (father[node] != father[father[node]])
father[node] = find(father[node]);
return father[node];
}
bool unite(int a, int b) {
a = find(a), b = find(b);
if (a == b)
return false;
if (h[a] < h[b])
father[a] = b;
else {
if (h[a] == h[b])
++ h[a];
father[b] = a;
}
return true;
}
int m;
struct Edge {
int a, b, c;
Edge(int _a = 0, int _b = 0, int _c = 0): a(_a), b(_b), c(_c) {}
} edges[8 * NMAX];
bool operator<(const Edge &a, const Edge &b) {
return a.c < b.c;
}
vector <int> all_positions;
void sweep() {
//Normalize
all_positions.clear();
for (int i = 1; i <= n; ++ i)
all_positions.push_back(points[i].y - points[i].x);
sort(all_positions.begin(), all_positions.end());
all_positions.resize(unique(all_positions.begin(), all_positions.end()) - all_positions.begin());
build(1,1,all_positions.size());
//Sort
sort(points + 1, points + n + 1);
//Sweep
pair <int, int> aux;
int coord;
for (int i = 1; i <= n; ++ i) {
coord = lower_bound(all_positions.begin(), all_positions.end(), points[i].y - points[i].x) - all_positions.begin() + 1;
aux = query(1, coord);
if (aux.second)
edges[++ m] = Edge(points[i].ind, aux.second, points[i].x + points[i].y - aux.first);
update(1, coord, points[i]);
}
}
void get_edges() {
m = 0;
for (int k = 0; k < 2; ++ k) {
for (int i = 0; i < 4; ++ i) {
sweep();
rotate();
}
reflect();
}
}
lint kruskal() {
sort(edges + 1, edges + m + 1);
init();
lint ans = 0;
for (int i = 1; i <= m; ++ i)
if (unite(edges[i].a, edges[i].b))
ans += edges[i].c;
return ans;
}
int main()
{
ofstream cout("metrou4.out");
cin >> t;
while (t --) {
cin >> n;
for (int i = 1; i <= n; ++ i) {
cin >> points[i].x >> points[i].y;
points[i].ind = i;
}
get_edges();
cout << kruskal() << '\n';
}
return 0;
}