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 ...
随机推荐
- 看linux正在运行的服务用哪个命令?
https://zhidao.baidu.com/question/117779006.html 查看服务进程:ps aux查看服务cpu利用:top查看服务对应端口:netstat -nlp pst ...
- Ubuntu 16.04下的安装RabbitMQ
安装 添加源 echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/ra ...
- Python中线程与互斥锁
了解之前我们先了解一下什么是多任务? 概念: 几个不同的事件在同时运行就是多任务, 这样的话, 我们有牵扯到了真的多任务, 假的多任务; 并行: 真的多任务, 通过电脑的核数来确定 并发: 假的多任务 ...
- jQuery核心函数的四种不同用法
核心函数根据实参的不同,有四种不同的用法. ①传一个函数作为参数 例如:$(function(){}) 作用:和window.onload = function(){}类似,它会在文档加载完成之后运行 ...
- day 46 Django 学习3 数据库单表操作以及反向解析
前情提要: Django 已经学了不少了, 今天学习链接数据库的操作.以及相关的反向解析等 一:反向解析 1:反向解析模板层 跳转时设定url会随着前面的路由改变而改变 2:反向解析之 ...
- jq03--基础函数
我们继续学习jq的一些函数,包括向jq对象添加.删除CSS属性以及遍历DOM树. 1.获取.设置CSS类 addClass()--向被选元素添加1个或多个类属性 .importance{font-we ...
- 多维标度法(MDS)的Python实现
多维标度法(multidimensional scaling,MDS)是一种在低维空间展示“距离”数据结构的多元数据分析技术,是一种将多维空间的研究对象( 样本 或 变量 ) 简化到低维空间进行定位. ...
- 剑指offer四十二之和为S的两个数字
一.题目 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 二.思路 数列满足递增,设两个头尾两个指针i和j,若ai + ...
- cygwin 安装.
在线安装, http://www.cygwin.com/ 64位的,下载安装. 先装的低配的,只有几个组件装了,不然全部装太大,下次需要再装... binutils gcc gdb windows ...
- MYSQL 复制详解
MySql 复制介绍 MySQL复制允许将主实例(master)上的数据同步到一个或多个从实例(slave)上,默认情况 下复制是异步进行的,从库也不需要一直连接到主库来同步数据 MySQL复制的数据 ...