• [JSOI2018] 战争


    一、题目

    点此看题

    二、解法

    哈哈哈,这道题我都给草过去了,计算几何学懂啦(sim)

    发现部落的管辖范围就是求凸包,那么我们先把两个部落的凸包求出来。

    任意取第一个凸包的一点 (a),第二个凸包的一点 (b),设位移向量是 (d),那么两个凸包管辖范围不交等价于向量 (v=a-b-d) 非零,发现 (a-b) 是一种闵可夫斯基和的形式,我们把第二个凸包的所有点取反,然后做闵可夫斯基和,问题变成了判断点 (d) 在不在合并后的凸包中。

    可以 (O(log n)) 快速判断,首先把凸包左下角的点平移到 ((0,0)),凸包的所有边本身就是有极角顺序的,设 (c_i) 为凸包上第 (i) 个点,翻译成叉积就是 (c_i imes c_{i+1}<0),也就是第 (i) 个点到第 (i+1) 个点有一个顺时针转角。

    首先判断边界情况,然后找到待判定顺时针方向上的第一个凸包上的点,做一下叉积就可以判断该点是否在凸包上了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define int long long
    const int M = 200005;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,k,q;
    struct point
    {
    	int x,y;
    	point(int X=0,int Y=0) : x(X) , y(Y) {}
    	point operator + (point b) {return point(x+b.x,y+b.y);}
    	point operator - (point b) {return point(x-b.x,y-b.y);}
    	int operator * (point b) {return x*b.y-y*b.x;}
    	bool operator < (const point &b) const {
    		return x==b.x?y<b.y:x<b.x;
    	}
    }a[M],b[M],c[M],v[M],s[M],t[M];
    void conv(point *a,int &n)
    {
    	int m=0;
    	sort(a+1,a+1+n);
    	for(int i=1;i<=n;i++)
    	{
    		while(m>1 && (a[i]-v[m-1])*(v[m]-v[m-1])<=0) m--;
    		v[++m]=a[i];
    	}
    	int tmp=m;
    	for(int i=n-1;i>=1;i--)
    	{
    		while(m>tmp && (a[i]-v[m-1])*(v[m]-v[m-1])<=0) m--;
    		v[++m]=a[i];
    	}
    	n=m-1;memcpy(a,v,sizeof v);
    }
    void merge()
    {
    	for(int i=1;i<=n;i++) s[i]=a[i%n+1]-a[i];
    	for(int i=1;i<=m;i++) t[i]=b[i%m+1]-b[i];
    	int i=1,j=1;c[++k]=a[1]+b[1];
    	while(i<=n && j<=m) k++,c[k]=c[k-1]+(s[i]*t[j]<=0?s[i++]:t[j++]);
    	while(i<=n) k++,c[k]=c[k-1]+s[i++];
    	while(j<=m) k++,c[k]=c[k-1]+t[j++];
    }
    int cmp(point x,point y)
    {
    	return x*y<0;
    }
    int ask(point x)
    {
    	if(c[k]*x<0 || x*c[2]<0) return 0;
    	int p=lower_bound(c+1,c+1+k,x,cmp)-c-1;
    	return (x-c[p])*(c[p%k+1]-c[p])>=0;
    }
    signed 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();
    	conv(a,n);conv(b,m);
    	merge();
    	conv(c,k);point bs=c[1];
    	for(int i=1;i<=k;i++) c[i]=c[i]-bs;
    	while(q--)
    	{
    		int x=read(),y=read();
    		printf("%d
    ",ask(point(x,y)-bs));
    	}
    }
    
  • 相关阅读:
    大白痴学习webmagic
    selenium docs
    centos6.5单用户模式拯救系统
    使用Squid做代理服务器,Squid单网卡透明代理配置详解(转)
    Redundant Call to Object.ToString()
    Specify a culture in string conversion explicitly
    Benefits of Cold Showers: 7 Reasons Why Taking Cool Showers Is Good For Your Health
    Why Creating a Meaningful Morning Routine Will Make You More Successful
    git图示所有分支的历史
    Rewriting History with Git Rebase
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15112379.html
Copyright © 2020-2023  润新知