LG P4557 [JSOI2018]战争

Description

九条可怜是一个热爱读书的女孩子。

在她最近正在读的一本小说中,描述了两个敌对部落之间的故事。第一个部落有 $n$ 个人,第二个部落有 $m$ 个人,每一个人的位置可以抽象成二维平面上坐标为 $(x_i,y_i)$的点。

在这本书中,人们有很强的领地意识,对于平面上的任何一个点,如果它被三个来自同一部落的人形成的三角形(可能退化成一条线段)包含(包括边界),那么这一个点就属于这一个部落的领地。如果存在一个点同时在两个阵营的领地中,那么这两个部落就会为了争夺这一个点而发生战争。

常年的征战让两个部落不堪重负,因此第二个部落的族长作出了一个英明的决定,他打算选择一个向量 $(dx,dy)$ ,让所有的族人都迁徙这个向量的距离,即所有第二阵营的人的坐标都变成 $(x_i+dx,y_i+dy)$

现在他计划了 $q$ 个迁徙的备选方案,他想要你来帮忙对每一个迁徙方案,计算一下在完成了迁徙之后,两个部落之间还会不会因为争夺领地而发生战争。

Solution

要求求出B凸包向指定方向移动一段距离是否与A凸包有交

考虑如果有交,那么存在$b+w=a$

整理得$w=a-b$,即为两个凸包的闵科夫斯基和

代码中的in函数有些bug

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,m,q,tot,top;
struct Node{
    long long x,y;
    Node operator +(const Node &z)const{return (Node){x+z.x,y+z.y};}
    Node operator -(const Node &z)const{return (Node){x-z.x,y-z.y};}
    long long operator *(const Node &z)const{return x*z.y-y*z.x;}
    long long dis(){return x*x+y*y;}
}A[100005],B[100005],base,sta[100005],s1[100005],s2[100005],s[200005];
inline int read(){
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
bool cmp(Node a,Node b){return a*b>0||!(a*b)&&a.dis()<b.dis();}
void Graham(Node *a,int &N){
    int k=1;
    for(int i=2;i<=N;i++)if(a[i].y<a[k].y||a[i].y==a[k].y&&a[i].x<a[k].x)k=i;
    swap(a[k],a[1]),base=a[1];
    for(int i=1;i<=N;i++)a[i]=a[i]-base;
    sort(a+2,a+N+1,cmp),top=2,sta[1]=a[1],sta[2]=a[2];
    for(int i=3;i<=N;i++){
        while(top>=2&&(sta[top]-sta[top-1])*(a[i]-sta[top-1])<=0)--top;
        sta[++top]=a[i];
    }
    for(int i=1;i<=top;i++)a[i]=sta[i]+base;
    N=top;
}
void Minkowski(){
    for(int i=1;i<n;i++)s1[i]=A[i+1]-A[i];s1[n]=A[1]-A[n];
    for(int i=1;i<m;i++)s2[i]=B[i+1]-B[i];s2[m]=B[1]-B[m];
    s[tot=1]=A[1]+B[1];
    int pos1=1,pos2=1;
    while(pos1<=n&&pos2<=m)++tot,s[tot]=s[tot-1]+(s1[pos1]*s2[pos2]>=0?s1[pos1++]:s2[pos2++]);
    while(pos1<=n)++tot,s[tot]=s[tot-1]+s1[pos1++];
    while(pos2<=m)++tot,s[tot]=s[tot-1]+s2[pos2++];
}
bool in(Node x){
    if(x*s[1]>0||s[tot]*x>0)return false;
    int temp=lower_bound(s+1,s+tot+1,x,cmp)-s-1;
    return (x-s[temp])*(s[temp%tot+1]-s[temp])<=0;
}
int main(){
    n=read(),m=read(),q=read();
    for(int i=1;i<=n;i++)A[i]=(Node){read(),read()};
    for(int i=1;i<=m;i++)B[i]=(Node){-read(),-read()};
    Graham(A,n),Graham(B,m),Minkowski(),Graham(s,tot),base=s[1];
    for(int i=1;i<=tot;i++)s[i]=s[i]-base;
    for(;q;q--)s[0]=(Node){read(),read()},printf("%d\n",in(s[0]-base));
    return 0;
}
[JSOI2018]战争

 

posted @ 2021-02-25 08:52  QDK_Storm  阅读(71)  评论(0编辑  收藏  举报