对于点集$A$,$B$,闵可夫斯基和$C=\{(x1+x2,y1+y2)|(x1,x2)\in A,(y1,y2)\in B\}$。
由此可知,对于两个凸包$A$,$B$的闵可夫斯基和$C$满足,$C$中的向量是所有$A$中向量与$B$中向量的和的并集。可以证明,$C$也是一个凸包。
现在问题是要求,对于询问向量$\vec{d}$,是否存在$\vec{a}\in A$,$\vec{b}\in B$,使得$\vec{a}=\vec{b}+\vec{d}$。
移项得$\vec{d}=\vec{a}-\vec{b}$,发现这是$B$中所有向量取反后与$A$的闵可夫斯基和。于是问题转化为,求$A$与$-B$的闵可夫斯基和$C$,并快速判断某个向量是否在$C$内。
求闵可夫斯基和有一个线性算法,正确性不会证明。
先求出$A$和$B$的凸包,再取出凸包上所有的边,这些边显然都分别是已经按极角排好序的向量。
初始时$C$只有一个点$\vec{a1}+\vec{b1}$,其中$a1$,$b1$分别是$A$和$B$凸包中的第一个点。
接下来类似归并排序地,按极角序从小到大依次插入新向量并维护凸包。
最后,凸包的尾部可能会出现一些多余点,直接删除或再求一次凸包即可。
得到凸包$C$后,问题只剩快速判断一个点$P$是否在凸包$C$内了。
很简单,将凸包中点以相对于凸包第一个点的极角序排好,二分找到$P$在其中哪个位置,向量叉积即可判断。
总复杂度$O(n\log n)$

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
int n,m,q,tot;
struct P{ ll x,y; }s,p[N],p1[N],p2[N],v1[N],v2[N],t[N],a[N];
P operator +(const P &a,const P &b){ return (P){a.x+b.x,a.y+b.y}; }
P operator -(const P &a,const P &b){ return (P){a.x-b.x,a.y-b.y}; }
ll operator *(const P &a,const P &b){ return a.x*b.y-a.y*b.x; }
ll len(P a){ return a.x*a.x+a.y*a.y; } bool cmp(const P &a,const P &b){ ll k=(a-s)*(b-s); return k ? k> : len(a-s)<len(b-s); } int Graham(P a[],int n){
rep(i,,n) t[i]=a[i];
rep(i,,n) if (t[i].x<t[].x || (t[i].x==t[].x && t[i].y<t[].y)) swap(t[],t[i]);
s=t[]; sort(t+,t+n+,cmp); int top=;
rep(i,,n){
while (top> && (t[top]-t[top-])*(t[i]-t[top-])<=) top--;
t[++top]=t[i];
}
rep(i,,top) a[i]=t[i];
return top;
} bool jud(P x){
P vx=x-p[];
if (vx*(p[tot]-p[])< || vx*(p[]-p[])>) return ;
int px=lower_bound(p+,p+tot+,x,cmp)-p-;
return (x-p[px])*(p[px%tot+]-p[px])<=;
} int main(){
freopen("bzoj5317.in","r",stdin);
freopen("bzoj5317.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
rep(i,,n) scanf("%lld%lld",&p1[i].x,&p1[i].y);
rep(i,,m) scanf("%lld%lld",&p2[i].x,&p2[i].y),p2[i].x=-p2[i].x,p2[i].y=-p2[i].y;
n=Graham(p1,n); m=Graham(p2,m);
rep(i,,n-) v1[i]=p1[i+]-p1[i]; v1[n]=p1[]-p1[n];
rep(i,,m-) v2[i]=p2[i+]-p2[i]; v2[m]=p2[]-p2[m];
p[]=p1[]+p2[]; tot=;
int l1=,l2=;
while (l1<=n || l2<=m)
tot++,p[tot]=p[tot-]+((l1<=n && (l2>m || (v1[l1]*v2[l2]>=))) ? v1[l1++] : v2[l2++]);
while (tot> && (p[tot]-p[tot-])*(p[]-p[tot-])<=) tot--;
s=p[]; P qs;
rep(i,,q) scanf("%lld%lld",&qs.x,&qs.y),printf("%d\n",jud(qs));
return ;
}

[BZOJ5317][JSOI2018]部落战争(闵可夫斯基和)的更多相关文章

  1. BZOJ5317 JSOI2018部落战争(凸包)

    即询问凸包是否有交.这显然可以直接求半平面交,但是复杂度O(q(n+m)),且没有什么优化空间. 更直接地表示,即相当于询问是否存在点a∈A,b∈B,使得a+d=b.移项,得到d=b-a.可以发现等式 ...

  2. 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 ...

  3. 【BZOJ5317】[JSOI2018]部落战争(凸包,闵可夫斯基和)

    [BZOJ5317][JSOI2018]部落战争(凸包,闵可夫斯基和) 题面 BZOJ 洛谷 题解 很明显我们只需要两个凸包\(A,B\). 假设询问给定的方向向量是\(v\). 那么现在就是判断\( ...

  4. BZOJ 5317: [Jsoi2018]部落战争

    传送门 写出式子,若存在 $a \in A$,$b \in B$,使得 $b+v=a$,那么此方案会产生冲突 即存在 $a \in A$,$b \in B$,使得 $v=a+(-b)$,设 $C=A+ ...

  5. 「JSOI2018」战争

    「JSOI2018」战争 解题思路 我们需要每次求给一个凸包加上一个向量后是否与另外一个凸包相交,也就是说是否存在 \[ b\in B,(b+w)\in A \] 这里 \(A, B\) 表示凸包内部 ...

  6. BZOJ2150: 部落战争

    题解: 把每个点拆成入点和出点,因为必须经过一次且只能经过一次.所以在两个点之间连一条上界=下界=1的边. 然后再s到每个入点连边,每个出点向t连边,点与点之间... 求最小流就可以过了... (感觉 ...

  7. BZOJ 2150: 部落战争 最大流

    2150: 部落战争 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php? ...

  8. BZOJ-2150部落战争(最小路径覆盖)

    2150: 部落战争 Time Limit: 10 Sec  Memory Limit: 259 MB Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国 ...

  9. 【洛谷】4304:[TJOI2013]攻击装置【最大点独立集】【二分图】2172: [国家集训队]部落战争【二分图/网络流】【最小路径覆盖】

    P4304 [TJOI2013]攻击装置 题目描述 给定一个01矩阵,其中你可以在0的位置放置攻击装置. 每一个攻击装置(x,y)都可以按照“日”字攻击其周围的8个位置(x-1,y-2),(x-2,y ...

随机推荐

  1. C# Func的同步、异步调用

    using System; namespace ActionDemo { class Program { static void Main(string[] args) { Console.Write ...

  2. ==和equals区别

    java中的数据类型,可分为两类:  1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean    他们之间的比较,应用双等号( ...

  3. MVVM设计模式的事件绑定

    为什么要事件绑定 这个问题其实是很好理解的,因为事件是丰富多样的,单纯的命令绑定远不能覆盖所有的事件.例如Button的命令绑定能够解决Click事件的需求,但Button的MouseEnter.窗体 ...

  4. python hash()和hashlib

    一.哈希算法 哈希算法:哈希算法并不是特定的算法而是一类算法的统称,只要是完成这种功能的算法都是哈希算法,哈希算法也叫做散列算法.同时这个过程是不可逆的,无法由key推导出data.判断一个哈希算法是 ...

  5. Java不为人知的小秘密

    Java中的main方法必须有一个外壳类,而且必须是静态的! Java中的所有函数都属于某个类的方法,所以main方法也不例外,必须放在一个类中才能编译运行. 例如: public class tex ...

  6. 公司xenserver搭建的使用

    [root@xenserver ~]# ls -l /dev/disk/by-path/total 0lrwxrwxrwx 1 root root  9 Jan 19 16:33 pci-0000:0 ...

  7. js对金额浮点数运算精度的处理方案

    浮点数产生的原因 浮点数转二进制,会出现无限循环数,计算机又对无限循环小数进行舍入处理 js弱语言的解决方案 方法一: 指定要保留的小数位数(0.1+0.2).toFixed(1) = 0.3;这个方 ...

  8. 转载:Google 官方应用架构的最佳实践指南 赞👍

    官方给的实践指南,很有实际的指导意义,  特别是对一些小公司,小团队,给了很好的参考意义. 原文地址: https://developer.android.com/topic/libraries/ar ...

  9. 洛谷P1725 琪露诺

    传送门啦 本人第一个单调队列优化 $ dp $,不鼓励鼓励? 琪露诺这个题,$ dp $ 还是挺好想的对不,但是暴力 $ dp $ 的话会 $ TLE $ ,所以我们考虑用单调队列优化. 原题中说她只 ...

  10. INSTEAD OF与AFTER触发器

    INSTEAD OF 触发器 AFTER 触发器(也叫“FOR”触发器)会在触发 insert.update 或是delect 动作之后执行.例如,一个 Employees 表上的 AFTER 触发器 ...