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);
}