• BZOJ 5317: [Jsoi2018]部落战争


    传送门

    写出式子,若存在 $a in A$,$b in B$,使得 $b+v=a$,那么此方案会产生冲突

    即存在 $a in A$,$b in B$,使得 $v=a+(-b)$,设 $C=A+(-B)$ 那么有 $v in C$,$+$ 表示闵可夫斯基和,$-$ 表示坐标符号取反

    所有直接求出 $A$ 和 $-B$ 的闵可夫斯基和的凸包,然后查询 $v$ 是否在凸包内即可

    注意直接求闵可夫斯基和的凸包可能会有一些平行的向量,为了方便查询,重新做一遍凸包即可

    我的做法会把凸包坐标变化,所以查询的向量也要跟着变化

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    typedef double db;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e5+7;
    struct poi {
        ll x,y;
        poi (ll a=0,ll b=0) { x=a,y=b; }
        inline poi operator + (const poi &tmp) const { return poi(x+tmp.x,y+tmp.y); }
        inline poi operator - (const poi &tmp) const { return poi(x-tmp.x,y-tmp.y); }
        inline bool operator < (const poi &tmp) const { return x!=tmp.x ? x<tmp.x : y<tmp.y; }
    }A[N],B[N],C[N],st[N],sum;
    inline ll Cross(poi A,poi B) { return A.x*B.y-A.y*B.x; }
    inline db Dot(poi A,poi B) { return A.x*B.x+A.y*B.y; }
    inline db Len(poi A) { return sqrt(Dot(A,A)); }
    inline bool cmp(const poi &A,const poi &B) { return Cross(A,B)>0||(Cross(A,B)==0&&Len(A)<Len(B)); }
    void Tubao(poi *P,int &tot)
    {
        sort(P+1,P+tot+1); sum=sum+P[1];/*如果此时求的是C的凸包P[1]=(0,0)没有贡献*/ for(int i=tot;i>=1;i--) P[i]=P[i]-P[1];
        sort(P+1,P+tot+1,cmp); int Top=0;
        for(int i=1;i<=tot;st[++Top]=P[i],i++)
            while(Top>1 && Cross(P[i]-st[Top-1],st[Top]-st[Top-1])>=0 ) Top--;
        tot=Top; for(int i=1;i<=tot;i++) P[i]=st[i];
    }
    int check(poi *P,int tot,poi A)
    {
        A=A-sum;
        if(Cross(A,P[2])>0||Cross(P[tot],A)>0) return 0;
        int pos=lower_bound(P+1,P+tot+1,A,cmp)-P-1; if(pos==tot) return 0;
        return Cross(A-P[pos],P[pos+1]-P[pos])<=0;
    }
    int n,m,T,Q;
    int main()
    {
        n=read(),m=read(),Q=read();
        for(int i=1;i<=n;i++) A[i].x=read(),A[i].y=read();
        for(int i=1;i<=m;i++) B[i].x=-read(),B[i].y=-read();
        Tubao(A,n); Tubao(B,m);
        int la=1,lb=1; C[++T]=A[1]+B[1];
        while(la<=n||lb<=m)
        {
            poi p1=A[la%n+1]+B[(lb-1)%m+1],p2=A[(la-1)%n+1]+B[lb%m+1];
            if(Cross(p1-C[T],p2-C[T])>=0) la++,C[++T]=p1;
            else lb++,C[++T]=p2;
        }
        Tubao(C,T);
        for(int i=1;i<=Q;i++)
        {
            int x=read(),y=read();
            printf("%d
    ",check(C,T,poi(x,y)));
        }
        return 0;
    }
  • 相关阅读:
    ubuntu18.04英文环境解决各种软件中文乱码问题
    Centos6两个镜像文件的合并方法
    将centos的yum源修改为阿里云的yum源
    Linux TOP 命令总结
    Nginx add SSL 证书 基础配置
    Nginx Http 核心模块中Server Location 配置
    df -h执行卡住不动问题解决
    Jetty Session Persistence By Redis
    Spring @Transactional配置知识梳理
    通用FTP Client模块设计与实现
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11444577.html
Copyright © 2020-2023  润新知