This is a harder version of the problem. In this version, n≤50000.
There are n distinct points in three-dimensional space numbered from 1 to n. The i-th point has coordinates (xi,yi,zi). The number of points n is even.
You’d like to remove all n points using a sequence of n2 snaps. In one snap, you can remove any two points a and b that have not been removed yet and form a perfectly balanced pair. A pair of points a and b is perfectly balanced if no other point c (that has not been removed yet) lies within the axis-aligned minimum bounding box of points a and b.
Formally, point c lies within the axis-aligned minimum bounding box of points a and b if and only if min(xa,xb)≤xc≤max(xa,xb), min(ya,yb)≤yc≤max(ya,yb), and min(za,zb)≤zc≤max(za,zb). Note that the bounding box might be degenerate.
Find a way to remove all points in n2 snaps.
The first line contains a single integer n (2≤n≤50000; n is even), denoting the number of points.
Each of the next n lines contains three integers xi, yi, zi (−108≤xi,yi,zi≤108), denoting the coordinates of the i-th point.
No two points coincide.
Output n2 pairs of integers ai,bi (1≤ai,bi≤n), denoting the indices of points removed on snap i. Every integer between 1 and n, inclusive, must appear in your output exactly once.
We can show that it is always possible to remove all points. If there are many solutions, output any of them.
inputCopy
6
3 1 0
0 3 0
2 2 0
1 0 0
1 3 0
0 1 0
outputCopy
3 6
5 1
2 4
inputCopy
8
0 1 1
1 0 1
1 1 0
1 1 1
2 2 2
3 2 2
2 3 2
2 2 3
outputCopy
4 5
1 6
2 7
3 8
In the first example, here is what points and their corresponding bounding boxes look like (drawn in two dimensions for simplicity, as all points lie on z=0 plane). Note that order of removing matters: for example, points 5 and 1 don’t form a perfectly balanced pair initially, but they do after point 3 is removed.
在三维空间中给出n个点(没有重复点), 每次删除一对点, 要求删除时没有点在该对点构成的矩形中(需要一点空间能力, 可以借助上面二维的图来理解一下), 输出任意的删除序列
首先考虑一下, 只要我们找到了一队可删的点, 就立即把它删除好了, 不用考虑后效性
贪心的来考虑, 我们将所有点按x, y, z升序排列.
首次将x, y相同的相邻两点删除, 因为已经排好序了, 这样一定没有其他点在其中
再一次将, x相同的相邻两点删除, 同理
最后一次直接输出相邻的2点即可
注意每次要删去已用过的点
仔细考虑
#include
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef long long LL;
const int INF = 1 << 30;
const int MAXN = 1e5+10;
struct node{
int x, y, z, id;
}a[MAXN];
bool cmp(node a, node b){
if(a.x != b.x) return a.x < b.x;
else{
if(a.y != b.y) return a.y < b.y;
else return a.z < b.z;
}
}
bool used[MAXN];
int n;
vector<node> ans;
int main() {
ios::sync_with_stdio(false);
cin >> n;
for(int i = 1; i <= n; ++i){
cin >> a[i].x >> a[i].y >> a[i].z;
a[i].id = i;
}
sort(a+1, a+1+n, cmp);
for(int i = 1; i < n; ++i){
if(a[i].x == a[i+1].x && a[i].y == a[i+1].y){
cout << a[i].id << ' ' << a[i+1].id << endl;
used[i] = used[i+1] = true;
++i;
}
}
for(int i = 1; i <= n; ++i)
if(!used[i])
ans.push_back(a[i]);
ms(used, 0);
for(int i = 0; i < ans.size(); ++i){
if(ans[i].x == ans[i+1].x){
cout << ans[i].id << ' ' << ans[i+1].id << endl;
used[i] = used[i+1] = true;
++i;
}
}
int cnt = 0;
for(int i = 0; i < ans.size(); ++i)
if(!used[i])
a[cnt++] = ans[i];
for(int i = 0; i < cnt; i+=2)
cout << a[i].id << ' ' << a[i+1].id << endl;
return 0;
}