IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> P4557-[JSOI2018]战争【凸包闵可夫斯基和】 -> 正文阅读

[数据结构与算法]P4557-[JSOI2018]战争【凸包闵可夫斯基和】

正题

题目连接:https://www.luogu.com.cn/problem/P4557


题目大意

给出两个点集 A , B A,B A,B q q q次询问给出一个向量 v v v,询问将 B B B中所有点加上向量 v v v后两个集合的凸包是否有交。

1 ≤ n , m , q ≤ 1 0 5 1\leq n,m,q\leq 10^5 1n,m,q105


解题思路

闵可夫斯基和定义了两个向量集合的和,这里只讨论凸包的闵可夫斯基和。

A + B A+B A+B,那么相当于以 A A A凸包绕着 B B B的凸包跑一圈形成的图形(位置不重要,这里的都是相对位置)。

然后求法就是实际上求和后的每条边是由原来的边组成的一个大凸包,所以我们直接把原来的两个凸包的边归并排序,然后再逐一算出每个点的位置就好了。

然后这个东西有什么用的,我也不知道。

但是看这道题,我们求出 A + ( ? B ) A+(-B) A+(?B),这样就大致 A A A B B B的位置的形状,此时对于询问向量 v v v,如果它在 A + ( ? B ) A+(-B) A+(?B)内那么就是有交的,否则就是无交的。

时间复杂度: O ( n log ? n ) O(n\log n) O(nlogn)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
const ll N=1e5+10;
struct vec{
	ll x,y;
	vec(ll xx=0,ll yy=0)
	{x=xx;y=yy;return;}
	ll len(){return x*x+y*y;}
}a[N],b[N],c[N],d[N],p[N<<1];
ll n,m,q,tot;
vector<vec> s;
vec operator+(const vec &a,const vec &b)
{return vec(a.x+b.x,a.y+b.y);}
vec operator-(const vec &a,const vec &b)
{return vec(a.x-b.x,a.y-b.y);}
ll operator^(const vec &a,const vec &b)
{return a.x*b.y-a.y*b.x;}
bool cmp(vec x,vec y)
{return (x.x==y.x)?(x.y<y.y):(x.x<y.x);}
bool cMp(vec x,vec y)
{return (x^y)>0||((x^y)==0&&x.len()<y.len());}
#define top (s.size()-1)
void Convex(vec *p,ll &n){
	while(!s.empty())s.pop_back();
	sort(p+1,p+1+n,cmp);vec bas=p[1];
	for(ll i=1;i<=n;i++)p[i]=p[i]-bas;
	sort(p+2,p+1+n,cMp);s.push_back(p[1]);
	for(ll i=2;i<=n;i++){
		while(top>0&&((s[top]-s[top-1])^(p[i]-s[top-1]))<=0)s.pop_back();
		s.push_back(p[i]);
	}
	for(ll i=0;i<=top;i++)p[i+1]=s[i]+bas;
	n=s.size();return;
}
#undef top
void Minkowski(){
	for(ll i=1;i<n;i++)c[i]=a[i+1]-a[i];c[n]=a[1]-a[n];
	for(ll i=1;i<m;i++)d[i]=b[i+1]-b[i];d[m]=b[1]-b[m];
	ll l=1,r=1;p[1]=a[1]+b[1];tot=1;
	while(l<=n&&r<=m)
		tot++,p[tot]=p[tot-1]+(((c[l]^d[r])>=0)?c[l++]:d[r++]);
	while(l<=n)tot++,p[tot]=p[tot-1]+c[l++];
	while(r<=m)tot++,p[tot]=p[tot-1]+d[r++];
	return;
}
bool Inside(vec x){
	if((x^p[1])>0||(x^p[tot])<0)return 0;
	ll pos=lower_bound(p+1,p+1+tot,x,cMp)-p-1;
	return ((x-p[pos])^(p[pos%tot+1]-p[pos]))<=0;
}
signed main()
{
	scanf("%lld%lld%lld",&n,&m,&q);
	for(ll i=1;i<=n;i++)scanf("%lld%lld",&a[i].x,&a[i].y);
	for(ll i=1;i<=m;i++)scanf("%lld%lld",&b[i].x,&b[i].y),b[i]=vec(0,0)-b[i];
	Convex(a,n);Convex(b,m);
	Minkowski();
	Convex(p,tot);
	vec bas=p[1];
	for(ll i=1;i<=tot;i++)p[i]=p[i]-bas;
	while(q--){
		vec x;
		scanf("%lld%lld",&x.x,&x.y);
		printf("%lld\n",Inside(x-bas));
	}
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 12:08:32  更:2022-05-10 12:09:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:29:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码