BZOJ5317:[JSOI2018]战争(闵可夫斯基和)
令 \(a\in A,b\in B\) 则移动向量 \(\omega\) 使得存在 \(b+\omega=a\)
那么 \(\omega\) 需要满足 \(\omega=a−b\)
黑科技:闵可夫斯基和
直接构造闵可夫斯基和 \(C={a+(−b)}\)
余下问题便是判断输入的移动向量是否在 \(C\) 内
可以强行使凸包的最下面为 \((0,0)\),这样只要找到与坐标轴夹角最接近的边就好了
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn(2e5 + 5);
const double eps(1e-13);
const double pi(acos(-1));
const double inf(1e15);
struct Point2D {
double x, y;
inline Point2D(double _x = 0, double _y = 0) {
x = _x, y = _y;
}
inline Point2D operator +(Point2D ad) const {
return Point2D(x + ad.x, y + ad.y);
}
inline Point2D operator -(Point2D ad) const {
return Point2D(x - ad.x, y - ad.y);
}
inline double operator ^(Point2D ad) const { //dot
return x * ad.x + y * ad.y;
}
inline double operator *(Point2D ad) const { //cross
return x * ad.y - y * ad.x;
}
inline Point2D operator *(double ad) const {
return Point2D(x * ad, y * ad);
}
inline double Len() {
return sqrt(x * x + y * y);
}
inline double Angle() {
return atan2(y, x);
}
};
struct Segment2D {
Point2D x, y;
inline Segment2D(Point2D _x = Point2D(0, 0), Point2D _y = Point2D(0, 0)) {
x = _x, y = _y;
}
};
inline Point2D CrossPoint2D(Segment2D a, Segment2D b) {
double k1, k2, t;
k1 = (b.y - a.x) * (a.y - a.x);
k2 = (a.y - a.x) * (b.x - a.x);
t = k2 / (k1 + k2);
return b.x + (b.y - b.x) * t;
}
Point2D tmp[maxn];
inline int Cmp(Point2D x, Point2D y) {
return (x - tmp[1]) * (y - tmp[1]) > 0;
}
inline void Graham(Point2D *a, int &len) {
int l = 0, mn = 0, i;
for (i = 1; i <= len; ++i)
if (!mn || (a[i].x < a[mn].x || (a[i].x == a[mn].x && a[i].y < a[mn].y))) mn = i;
swap(a[1], a[mn]), tmp[l = 1] = a[1], sort(a + 2, a + len + 1, Cmp);
for (i = 2; i <= len; ++i) {
while (l > 1 && (a[i] - tmp[l - 1]) * (tmp[l] - tmp[l - 1]) >= 0) --l;
tmp[++l] = a[i];
}
for (i = 1; i <= l; ++i) a[i] = tmp[i];
len = l;
}
int n, m, q, len;
Point2D a[maxn], b[maxn], c[maxn], p;
inline void Minkowski() {
int i, j;
c[len = 1] = a[1] + b[1], a[0] = a[1], b[0] = b[1];
for (i = 1; i < n; ++i) a[i] = a[i + 1] - a[i];
for (i = 1; i < m; ++i) b[i] = b[i + 1] - b[i];
a[n] = a[0] - a[n], b[m] = b[0] - b[m];
for (i = j = 1; i <= n || j <= m; )
if (j > m || (i <= n && a[i] * b[j] >= 0)) ++len, c[len] = c[len - 1] + a[i++];
else ++len, c[len] = c[len - 1] + b[j++];
}
inline int Query() {
int l, r, mid, cur = 2;
p = p - c[1];
if (c[len] * p > 0 || p * c[2] > 0) return 0;
l = 2, r = len - 1;
while (l <= r) {
mid = (l + r) >> 1;
if (c[mid] * p > 0) l = mid + 1, cur = mid;
else r = mid - 1;
}
return (p - c[cur]) * (c[cur + 1] - c[cur]) <= 0;
}
int main() {
int i;
scanf("%d%d%d", &n, &m, &q);
for (i = 1; i <= n; ++i) scanf("%lf%lf", &a[i].x, &a[i].y);
for (i = 1; i <= m; ++i) scanf("%lf%lf", &b[i].x, &b[i].y), b[i] = b[i] * -1;
Graham(a, n), Graham(b, m), Minkowski(), Graham(c, len);
for (i = 2; i <= len; ++i) c[i] = c[i] - c[1];
for (i = 1; i <= q; ++i) scanf("%lf%lf", &p.x, &p.y), printf("%d\n", Query());
return 0;
}
BZOJ5317:[JSOI2018]战争(闵可夫斯基和)的更多相关文章
- [BZOJ5317][JSOI2018]部落战争(闵可夫斯基和)
对于点集$A$,$B$,闵可夫斯基和$C=\{(x1+x2,y1+y2)|(x1,x2)\in A,(y1,y2)\in B\}$.由此可知,对于两个凸包$A$,$B$的闵可夫斯基和$C$满足,$C$ ...
- BZOJ5317 JSOI2018部落战争(凸包)
即询问凸包是否有交.这显然可以直接求半平面交,但是复杂度O(q(n+m)),且没有什么优化空间. 更直接地表示,即相当于询问是否存在点a∈A,b∈B,使得a+d=b.移项,得到d=b-a.可以发现等式 ...
- 洛谷P4557 [JSOI2018]战争(闵可夫斯基和+凸包)
题面 传送门 题解 看出这是个闵可夫斯基和了然而我当初因为见到这词汇是在\(shadowice\)巨巨的\(Ynoi\)题解里所以压根没敢学-- 首先您需要知道这个 首先如果有一个向量\(w\)使得\ ...
- [JSOI2018]战争(闵可夫斯基和)
害怕,可怜几何题 果然不会 题目就是说给你两个凸包,每次询问给你一个向量 \(c\) 问你能不能从两个凸包 \(A\) , \(B\) 里分别找到一个点 \(a\) , \(b\) 满足 \(a+c= ...
- 2019.02.21 bzoj5317: [Jsoi2018]部落战争(凸包+Minkowski和)
传送门 题意:qqq次询问把一个凸包整体加一个向量(x,y)(x,y)(x,y)之后是否与另外一个凸包相交. 思路:转化一下发现只要会求A+B={v⃗=a⃗+b⃗∣a⃗∈A,b⃗∈B}A+B=\{\v ...
- P4557 [JSOI2018]战争
首先可以题目描述的两个点集是两个凸包,分别设为A和B. 考虑一个向量w不合法的条件. 即存在b+w=a,其中a属于A,b属于B. 也就是a-b=w. 即对b取反后和a的闵可夫斯基和. 求出闵可夫斯基和 ...
- [JSOI2018]战争
题目描述 九条可怜是一个热爱读书的女孩子. 在她最近正在读的一本小说中,描述了两个敌对部落之间的故事.第一个部落有 nnn 个人,第二个部落有 mmm 个人,每一个人的位置可以抽象成二维平面上坐标为 ...
- 【LuoguP4557】[JSOI2018]战争
题目链接 题意 给你两个点集. q次询问 , 每次把其中一个点集往一个方向移动 , 问两个点集的凸包还有没有交. Sol 闵可夫斯基和板子题. 把问题做如下转换: 我们本来两个凸包相交是相当于是对于移 ...
- 计算几何细节梳理&模板
点击%XZY巨佬 向量的板子 #include<bits/stdc++.h> #define I inline using namespace std; typedef double DB ...
随机推荐
- java 中什么是aop
AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...
- 六:MyBatis学习总结(六)——调用存储过程
一.提出需求 查询得到男性或女性的数量, 如果传入的是0就女性否则是男性 二.准备数据库表和存储过程 create table p_user( id int primary key auto_incr ...
- P1484 种树
P1484 种树 题意: 在n个数中选出至多k个数,且两两不相邻,并使所选数的和最大. n<=500000 思路 先建一个堆,把所有点扔进去,当取出队首元素时累加到答案时,把它和它左右两个点一 ...
- Maven国内阿里镜像(Maven下载慢的解决方法)
Maven是当前流行的项目管理工具,但官方的库在国外经常连不上,连上也下载速度很慢.国内oschina的maven服务器很早之前就关了.今天发现阿里云的一个中央仓库,亲测可用. <mirror& ...
- 支付宝小程序自定义弹窗插件|支付宝dialog插件|model插件
支付宝小程序自定义弹窗组件wcPop|小程序自定义对话框|actionSheet弹窗模板 支付宝小程序官方提供的alert提示框.dialog对话框.model弹窗功能比较有限,有些都不能随意自定义修 ...
- TapTap推广统计逻辑
当我们在Taptap上访问某款游戏时,比如https://www.taptap.com/app/34762,taptap会记录下这次访问,它是怎么做的呢. 首先,用记事本打开这个网址,在head部分看 ...
- Android学习之一
- [webpack]path、publicPath、--content-base 理解
附源码:http://files.cnblogs.com/files/chenshao/startPublic.rar 'use strict'; var webpack = require('web ...
- 【树】Construct Binary Tree from Inorder and Postorder Traversal
题目: Given inorder and postorder traversal of a tree, construct the binary tree. 思路: 后序序列的最后一个元素就是树根, ...
- Linux 命令学习之rm
功能说明: rm 命令是对文件或目录进行删除操作. 语法:rm [-dfirv][--help][--version][文件或目录...] 补充说明:执行rm指令可删除文件或目录,如欲删除目录必须加上 ...