• 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
    ",in(s[0]-base));
        return 0;
    }
    [JSOI2018]战争
  • 相关阅读:
    excel 常用小技巧
    如何以正确的顺序重新安装驱动程序
    kaby LAKE 仅支持 Windows10
    关闭远程计算机CMD命令
    根据IP查主机名
    Charles安装与使用
    常用的算法思想总结
    iOS学习之单例模式
    PHP之简单实现MVC框架
    Objective-C 继承和多态
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14444953.html
Copyright © 2020-2023  润新知