2018 ACM-ICPC World Finals Gym-102482H Single Cut of Failure

题目传送门

分析:
(被吊打的日子开始了。。。)
首先要发现一个奇妙的结论,由于一条线两端会在矩形两个不同的边界上,于是我们切两条对角线,一定能够切掉所有线
所以答案不会超过2。。
于是我们开始考虑所有线能不能一刀切
我们把矩形拆开看做数轴

进行这样的转换之后,我们实际上是要求一个区间,使得这个区间与所有蓝色区间有交,但是不包含任何一个区间
相当于只能包含每一个蓝色区间恰好一个端点
用两个点向右单调移动,打个标记即可维护
就是转化时的输入输出有点恶心2333

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

#define maxn 5000005
#define MOD 998244353

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,W,H;
int col[maxn],Num[maxn];
int P1[maxn],P2[maxn];
int b[maxn],N;
bool vis[maxn];
int Sz;

inline int getnum(int x,int y)
{
	if(!x)return y;
	if(y==H)return H+x;
	if(x==W)return 2*H+W-y;
	if(!y)return 2*H+2*W-x;
	return 0;
}

inline void print(int x)
{
	if(x<=H)printf("%.1lf %.1lf",0.0,x*0.5);
	else if(x<=H+W)printf("%.1lf %.1lf",(x-H)*0.5,H*0.5);
	else if(x<=2*H+W)printf("%.1lf %.1lf",W*0.5,(2*H+W-x)*0.5);
	else printf("%.1lf %.1lf",(2*W+2*H-x)*0.5,0.0);
}

int main()
{
	n=getint(),W=getint()*2,H=getint()*2;
	for(int i=1;i<=n;i++)
	{
		int x=getint()*2,y=getint()*2;
		b[++N]=P1[i]=getnum(x,y),b[++N]=P1[i]+1;
		x=getint()*2,y=getint()*2;
		b[++N]=P2[i]=getnum(x,y),b[++N]=P2[i]+1;
	}
	sort(b+1,b+N+1),N=unique(b+1,b+N+1)-b-1;
	for(int i=1;i<=n;i++)
	{
		int tmp=lower_bound(b+1,b+N+1,P1[i])-b;
		col[tmp]=i,Num[tmp]=P1[i];
		tmp=lower_bound(b+1,b+N+1,P2[i])-b;
		col[tmp]=i,Num[tmp]=P2[i];
	}
	int now=2;
	for(int i=2;i<=N;i+=2)
	{
		while(now<N&&!vis[col[now+1]])vis[col[now+1]]=1,now+=2,Sz++;
		if(Sz==n){printf("1\n"),print(Num[i-1]+1),printf(" "),print(Num[now-1]+1),printf("\n");return 0;}
		vis[col[i+1]]=0,Sz--;
	}
	W/=2,H/=2;
	printf("2\n%.1lf %d %.1lf %d\n%.1lf %d %.1lf %d\n",0.5,0,W-0.5,H,0.5,H,W-0.5,0);
}

posted @ 2020-06-25 20:34  Izayoi_Doyo  阅读(367)  评论(0编辑  收藏  举报