P4557-[JSOI2018]战争【凸包,闵可夫斯基和】

1|0正题

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


1|1题目大意

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

1n,m,q105


1|2解题思路

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

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

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

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

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

时间复杂度:O(nlogn)


1|3code

#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; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/16250872.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示