题目
CF
在三维空间内给你 nnn 个点坐标 (xi,yi,zi)(x_i,y_i,z_i)(xi?,yi?,zi?) ,保证 nnn 为偶数,每次可以配对两个点然后删去这两个点 a,ba,ba,b ,但要满足以他们为顶点构成的空间内没有点(包括边界),即没有点 ccc 满足
,输出 nnn 对方案?
n≤50000;xi,yi,zi≤108n\le50000;x_i,y_i,z_i\le 10^8n≤50000;xi?,yi?,zi?≤108
思路
非常巧妙,时间复杂度为 O(dnlogn)O(dnlogn)O(dnlogn) 其中 ddd 为空间维数
我们考虑一维时候方案非常显然,挨着配对即可,…注意此时 nnn 为奇数时可以留下来任意一个点此时固定 xix_ixi?
考虑而为时候方案,我们可以对每一条线 xix_ixi? 上的点做一维操作,然后就保证剩下点的 xix_ixi? 互不相等,又用类似方法即可
更高维度以此类推。
于是我们先固定两维 (xi,yi)(x_i,y_i)(xi?,yi?) 然后配对,然后固定一维 xix_ixi? 再配对,最后剩下的点再配对即可
体现为多个sort…
代码
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
bool f=0;int x=0;char c=getchar();while(c<'0'||'9'<c){
if(c=='-')f=1;c=getchar();}while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();return !f?x:-x;
}
#define MAXN 500000
#define INF 0x3f3f3f3f
struct node{
int x,y,z,id,f;friend bool operator < (node a,node b){
return (a.f==b.f?(a.x==b.x?(a.y==b.y?a.z<b.z:a.y<b.y):a.x<b.x):a.f<b.f);}
}a[MAXN+5];
int main(){
int n=read();for(int i=1;i<=n;i++){
int x=read(),y=read(),z=read();a[i]=(node){
x,y,z,i,0};}sort(a+1,a+n+1);for(int i=1;i<n;i++)if(!a[i].f&&!a[i+1].f&&a[i].x==a[i+1].x&&a[i].y==a[i+1].y){
printf("%d %d\n",a[i].id,a[i+1].id);a[i].f=1,a[i+1].f=1;}sort(a+1,a+n+1);for(int i=1;i<n;i++)if(!a[i].f&&!a[i+1].f&&a[i].x==a[i+1].x){
printf("%d %d\n",a[i].id,a[i+1].id);a[i].f=1,a[i+1].f=1;}sort(a+1,a+n+1);for(int i=1;i<n;i++)if(!a[i].f&&!a[i+1].f){
printf("%d %d\n",a[i].id,a[i+1].id);a[i].f=1,a[i+1].f=1;}return 0;
}
思考
以后遇到多维度问题可以想想最简单一维或者两维怎么做,或者理解为固定 d?1d-1d?1 维,只研究剩下的一个维度进行思考