害怕,可怜几何题

果然不会

题目就是说给你两个凸包,每次询问给你一个向量 \(c\) 问你能不能从两个凸包 \(A\) , \(B\) 里分别找到一个点 \(a\) , \(b\) 满足 \(a+c=b\) 。

考虑怎样的向量可以满足。

发现只有让B中的每一个点-A中的每一个点的集合中的向量可以满足。因为把上面的式子化一下就是 \(c=b-a\) 。

凸包B中的点集减去凸包A中的点集。这不是闵可夫斯基和吗?

所以我们把两个凸包的闵可夫斯基和求出,然后每一个询问查看给的向量在不在闵可夫斯基和中即可。

代码极丑,不过我判向量是不是在凸包里是把凸包切成上下两个凸包,然后分类讨论求的。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define int long long
const int N=501000;
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int top1,top2,top;
struct node{
int x,y;
node (int xx=0,int yy=0){
x=xx,y=yy;
}
}stack1[N],stack2[N],a[N],b[N],ans[N],ans1[N];
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);
}
bool cmp(node a,node b){
if(a.x==b.x)return a.y<b.y;
else return a.x<b.x;
}
int chaji(node a,node b){
return a.x*b.y-a.y*b.x;
}
bool judge(node a,node b,node c){
return chaji(b-c,a-b)<=0;
}
int n,m;
void tubao1(){
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
while(top1>1&&judge(a[i],stack1[top1],stack1[top1-1]))top1--;
stack1[++top1]=a[i];
}
int k=top1;
for(int i=n-1;i>=1;i--){
while(top1>k&&judge(a[i],stack1[top1],stack1[top1-1]))top1--;
stack1[++top1]=a[i];
}
top1--;
}
void tubao2(){
sort(b+1,b+1+m,cmp);
for(int i=1;i<=m;i++){
while(top2>1&&judge(b[i],stack2[top2],stack2[top2-1]))top2--;
stack2[++top2]=b[i];
}
int k=top2;
for(int i=m-1;i>=1;i--){
while(top2>k&&judge(b[i],stack2[top2],stack2[top2-1]))top2--;
stack2[++top2]=b[i];
}
top2--;
}
void sum(){
for(int i=1;i<=top1;i++)a[i]=stack1[i+1]-stack1[i];
for(int i=1;i<=top2;i++)b[i]=stack2[i+1]-stack2[i];
ans[top=1]=stack1[1]+stack2[1];
int now1=1,now2=1;
while(now1<=top1&&now2<=top2)top++,ans[top]=ans[top-1]+(chaji(a[now1],b[now2])>=0?a[now1++]:b[now2++]);
while(now1<=top1)top++,ans[top]=ans[top-1]+a[now1++];
while(now2<=top2)top++,ans[top]=ans[top-1]+b[now2++];
top--;
}
bool in(node x){
if(x.x<ans[1].x||x.x>ans[top1].x)return false;
if(x.x==ans[1].x){
if(x.y>=ans[1].y&&x.y<=ans1[1].y)return true;
else return false;
}
if(x.x==ans[top1].x){
if(x.y>=ans[top1].y&&x.y<=ans1[top2].y)return true;
else return false;
}
int A=lower_bound(ans+1,ans+1+top1,x,cmp)-ans;
int B=lower_bound(ans1+1,ans1+1+top2,x,cmp)-ans1;
if(chaji(ans1[B]-x,ans1[B-1]-x)>=0&&chaji(ans[A-1]-x,ans[A]-x)>=0)return true;
else return false;
}
int q;
signed main(){
n=read();m=read();q=read();
for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read();
tubao1();
for(int i=1;i<=m;i++)b[i].x=-read(),b[i].y=-read();
tubao2();
sum();
for(int i=1;i<=top;i++)
if(ans[i+1].x<ans[i].x){top1=i;break;}
for(int i=top1;i<=top+1;i++)
ans1[i-top1+1]=ans[i];
top2=top+1-top1+1;
while(ans[top1-1].x==ans[top1].x)top1--;
while(ans1[top2-1].x==ans1[top2].x)top2--;
for(int i=1;i<=top2/2ll;i++)swap(ans1[i],ans1[top2-i+1]);
while(q--){
int A=read(),B=read();
node x=node(A,B);
if(in(x))printf("1\n");
else printf("0\n");
}
return 0;
}

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

  1. BZOJ5317:[JSOI2018]战争(闵可夫斯基和)

    令 \(a\in A,b\in B\) 则移动向量 \(\omega\) 使得存在 \(b+\omega=a\) 那么 \(\omega\) 需要满足 \(\omega=a−b\) 黑科技:闵可夫斯基 ...

  2. [BZOJ5317][JSOI2018]部落战争(闵可夫斯基和)

    对于点集$A$,$B$,闵可夫斯基和$C=\{(x1+x2,y1+y2)|(x1,x2)\in A,(y1,y2)\in B\}$.由此可知,对于两个凸包$A$,$B$的闵可夫斯基和$C$满足,$C$ ...

  3. 洛谷P4557 [JSOI2018]战争(闵可夫斯基和+凸包)

    题面 传送门 题解 看出这是个闵可夫斯基和了然而我当初因为见到这词汇是在\(shadowice\)巨巨的\(Ynoi\)题解里所以压根没敢学-- 首先您需要知道这个 首先如果有一个向量\(w\)使得\ ...

  4. P4557 [JSOI2018]战争

    首先可以题目描述的两个点集是两个凸包,分别设为A和B. 考虑一个向量w不合法的条件. 即存在b+w=a,其中a属于A,b属于B. 也就是a-b=w. 即对b取反后和a的闵可夫斯基和. 求出闵可夫斯基和 ...

  5. [JSOI2018]战争

    题目描述 九条可怜是一个热爱读书的女孩子. 在她最近正在读的一本小说中,描述了两个敌对部落之间的故事.第一个部落有 nnn 个人,第二个部落有 mmm 个人,每一个人的位置可以抽象成二维平面上坐标为 ...

  6. 【LuoguP4557】[JSOI2018]战争

    题目链接 题意 给你两个点集. q次询问 , 每次把其中一个点集往一个方向移动 , 问两个点集的凸包还有没有交. Sol 闵可夫斯基和板子题. 把问题做如下转换: 我们本来两个凸包相交是相当于是对于移 ...

  7. 计算几何细节梳理&模板

    点击%XZY巨佬 向量的板子 #include<bits/stdc++.h> #define I inline using namespace std; typedef double DB ...

  8. HHHOJ #151. 「NOI模拟 #2」Nagisa

    计算几何板子题(我才没有拷板子的说--) 众所周知,三角形的重心坐标是\((\frac{x_1+x_2+x_3}{3},\frac{y_1+y_2+y_3}{3})\) 然后我们发现如果我们有一个点集 ...

  9. 【学习笔记】Minkowski和

    这还是个被我咕了N久的玩意 Minkowski和是一个奇怪的玩意 他长这样 $S={a+b \| a \in A , b \in B}$ AB可以是点集也可是向量集(显然) 他可以处理一些奇怪的东西 ...

随机推荐

  1. Java循环遍历中直接修改遍历对象

    Java 循环遍历中直接修改遍历对象如下,会报异常: for (ShopBaseInfo sp: sourceList) { if(sp.getId()==5){ sourceList.remove( ...

  2. H_Dp

    <span style="color:#000099;">/* H - 简单dp 例题扩展 Time Limit:3000MS Memory Limit:65536KB ...

  3. 随机获取一个集合(List, Set)中的元素,随机获取一个Map中的key或value

    利用Java提供的Random类.从List或Set中随机取出一个元素,从Map中随机获取一个key或value. 因为Set没有提供get(int index)方法,仅仅能先获取一个随机数后.利用一 ...

  4. 去掉文本框前后的空格(JS+JQuery)

    表单验证时,需要去除文本框前后的空格才可以正确通过验证.以前看到过一句话:任何设计和代码都要对用户足够宽容. <input type="text" class="p ...

  5. Linux - vim的基本使用

    通过which指令来查看文件位置! [root@local ~]# which vim /usr/bin/vim [root@local ~]# which vi /usr/bin/vi [root@ ...

  6. html5 初探

    html5是越来越火了.小小菜鸟也来学习学习. 相比于之前的几个版本,HTML5提供了更加丰富的多媒体标签使得音乐,视频的播放不用再借助于flah了.不过暂时各浏览器间样式还是有差别. 除此之外,表单 ...

  7. [.Net] DataTable添加列和行的三种方法

    #region 方法一: DataTable tblDatas =new DataTable("Datas"); DataColumn dc =null; dc = tblData ...

  8. POJ3414 Pots

    题目: 给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作 FILL(i)        将第i个容器从水龙头里装满(1 ≤ i ≤ 2); DROP(i)        将第i个容器抽干 ...

  9. FluentScheduler定时器

    项目需要一个按时执行的任务,每隔几分钟执行一个,或者每隔几小时执行一次等等,这个时候就需要一个定时的功能,最简单的就是用Timer自己写一个,但是自己写的性能等各方面有可能不健全等等,而现在开源的库也 ...

  10. python之路——迭代器和生成器

    阅读目录 楔子 python中的for循环 可迭代协议 迭代器协议 为什么要有for循环 初识生成器 生成器函数 列表推导式和生成器表达式 本章小结 生成器相关的面试题 返回顶部 楔子 假如我现在有一 ...