P6948 [ICPC 2018 WF] Single Cut of Failure
P6948\(\mathbf{} \begin{Bmatrix} \frac{{\Large LUOGU-P6948} }{{\color{Red}\Large Solution} }\mathbf{} {No.8} \end{Bmatrix}\times{}\) NeeDna
本题解思路来源于 Aguin 和一位学长。
拿到本题我们发现两条对角线一定可以满足任意情况,所以只用考虑答案是否为 1 即可这里用一个奇妙的做法,我们把这个矩形从一个顶点断开并沿边缘展开,那么原本的线段就变成了若干个区间。我们发现两条线段有交等价于现在的两个区间有交且不包含。而且发现无论从那个顶点断开都不影响两条直线相交的判断。
于是我们只需要判断能够找到一个区间与所有区间都相交。这一步好像做法很多。一种是,相交的必要条件是 左端点在 右端点左边, 右端点在 左端点右边。那么找到所有区间右端点最小值和左端点最大值,作为找到的区间,再判断是否有包含即可。另一种是,我们只需要找到一个区间恰好包含所有的属于不同区间的端点,用双指针扫一遍也可以。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
typedef pair<int, int> pii;
bool vis[maxn];
vector<pii> v;
int n, w, h;
inline int cal(int x, int y) {
if(x == 0) return y;
if(y == h) return h + x;
if(x == w) return 2 * h + w - y;
return 2 * (h + w) - x;
}
inline void get(double t, double& x, double& y) {
if(t <= h) x = 0, y = t;
else if(t <= h + w) x = t - h, y = h;
else if(t <= 2 * h + w) x = w, y = 2 * h + w - t;
else x = 2 * (h + w) - t, y = 0;
}
int main() {
cin>>n>>w>>h;
for(int i = 0; i < n; ++i) {
int X1, Y1, X2, Y2;
cin>>X1>>Y1>>X2>>Y2;
v.push_back(pii(cal(X1, Y1), i));
v.push_back(pii(cal(X2, Y2), i));
}
sort(v.begin(), v.end());
int sz = int(v.size()), p = 0, cnt = 0, one = 0;
for(int i=0;i<sz;++i) {
if(p == i)vis[v[i].second]=true,++p,++cnt;
while(!vis[v[p].second])vis[v[p].second]=true,p=(p+1)%sz,++cnt;
if(cnt == n) {
double ax1, ay1, ax2, ay2;
get(v[i].first - 0.5, ax1, ay1);
get(v[p].first - 0.5, ax2, ay2);
printf("1\n%.8f %.8f %.8f %.8f\n", ax1, ay1, ax2, ay2);
one = 1; break;
}
vis[v[i].second] = false, --cnt;
}
if(!one) printf("2\n0.5 0 %.8f %.8f\n0 %.8f %.8f %.8f\n", w - 0.5, 1.0 * h, h - 0.5, 1.0 * w, 0.5);
return 0;
}

浙公网安备 33010602011771号