UVA10256 The Great Divide

洛谷传送门

UVA 传送门

考虑对两个点集求出凸包,显然如果这两个凸包相离就合法,然后问题就转化成了这两个凸包是否有交。

设红点凸包包围的点集为 A,蓝点凸包包围的点集为 B,问题为询问是否 aA,bB,a=b,即 ab=0

于是对所有蓝点取反,求出新的蓝点凸包,再与红点凸包计算它们闵可夫斯基和的凸包,如果 (0,0) 在它的内部(包含边界),就说明 AB 有交,输出 No;否则输出 Yes

时间复杂度 O((n+m)log(n+m)),瓶颈在于对点排序。

code
const int maxn = 510;
int n, m, stk[maxn], top;
struct node {
int x, y;
node(int a = 0, int b = 0) : x(a), y(b) {}
};
node operator + (node a, node b) {
return node(a.x + b.x, a.y + b.y);
}
node operator - (node a, node b) {
return node(a.x - b.x, a.y - b.y);
}
int operator * (node a, node b) {
return a.x * b.y - a.y * b.x;
}
bool cmp(node a, node b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
vector<node> convex(vector<node> vc) {
sort(vc.begin(), vc.end(), cmp);
top = 0;
int n = (int)vc.size();
if (n == 1) {
return vc;
}
for (int i = 0; i < n; ++i) {
while (top >= 2 && (vc[stk[top]] - vc[stk[top - 1]]) * (vc[i] - vc[stk[top - 1]]) <= 0) {
--top;
}
stk[++top] = i;
}
vector<node> res;
for (int i = 1; i < top; ++i) {
res.pb(vc[stk[i]]);
}
top = 0;
for (int i = n - 1; ~i; --i) {
while (top >= 2 && (vc[stk[top]] - vc[stk[top - 1]]) * (vc[i] - vc[stk[top - 1]]) <= 0) {
--top;
}
stk[++top] = i;
}
for (int i = 1; i < top; ++i) {
res.pb(vc[stk[i]]);
}
return res;
}
vector<node> mkfsj(vector<node> a, vector<node> b) {
int n = (int)a.size(), m = (int)b.size();
vector<node> va(n), vb(m), res;
res.pb(a[0] + b[0]);
for (int i = 0; i < n; ++i) {
va[i] = a[(i + 1) % n] - a[i];
}
for (int i = 0; i < m; ++i) {
vb[i] = b[(i + 1) % m] - b[i];
}
int i = 0, j = 0;
while (i < n && j < m) {
res.pb(res.back() + (va[i] * vb[j] >= 0 ? va[i++] : vb[j++]));
}
while (i < n) {
res.pb(res.back() + va[i++]);
}
while (j < m) {
res.pb(res.back() + vb[j++]);
}
res.erase(res.begin());
return res;
}
bool check(vector<node> a, vector<node> b) {
vector<node> res = mkfsj(a, b);
node O;
int n = (int)res.size();
for (int i = 1; i < n; ++i) {
if ((O - res[i - 1]) * (res[i] - res[i - 1]) > 0) {
return 0;
}
}
return 1;
}
void solve() {
vector<node> a, b;
for (int i = 0, x, y; i < n; ++i) {
scanf("%d%d", &x, &y);
a.pb(node(x, y));
}
for (int i = 0, x, y; i < m; ++i) {
scanf("%d%d", &x, &y);
b.pb(node(-x, -y));
}
vector<node> v1 = convex(a), v2 = convex(b);
puts(check(v1, v2) ? "No" : "Yes");
}
int main() {
while (scanf("%d%d", &n, &m) == 2 && n) {
solve();
}
return 0;
}
posted @   zltzlt  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示