Balanced Removals(Codeforces Global Round 5-C)(贪心)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_37555704/article/details/102617529

题目

CF
在三维空间内给你 n n 个点坐标 ( x i , y i , z i ) (x_i,y_i,z_i) ,保证 n n 为偶数,每次可以配对两个点然后删去这两个点 a , b a,b ,但要满足以他们为顶点构成的空间内没有点(包括边界),即没有点 c c 满足在这里插入图片描述
,输出 n n 对方案?
n 50000 ; x i , y i , z i 1 0 8 n\le50000;x_i,y_i,z_i\le 10^8

思路

非常巧妙,时间复杂度为 O ( d n l o g n ) O(dnlogn) 其中 d d 为空间维数
我们考虑一维时候方案非常显然,挨着配对即可,…注意此时 n n 为奇数时可以留下来任意一个点此时固定 x i x_i
考虑而为时候方案,我们可以对每一条线 x i x_i 上的点做一维操作,然后就保证剩下点的 x i x_i 互不相等,又用类似方法即可
更高维度以此类推。
于是我们先固定两维 ( x i , y i ) (x_i,y_i) 然后配对,然后固定一维 x i x_i 再配对,最后剩下的点再配对即可
体现为多个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 1 d-1 维,只研究剩下的一个维度进行思考

猜你喜欢

转载自blog.csdn.net/qq_37555704/article/details/102617529