zoukankan      html  css  js  c++  java
  • P4557 [JSOI2018]战争 题解

    Luogu

    Description.

    有两个部落,每个部落有一些营地,对应为二维平面上的一些点。
    定义两个部落会发生重读,当且仅当满足以下条件之一。
    定义一个部落的控制范围是它所有营地构成的凸包。
    定义两个部落会发生冲突,当且仅当一个部落的一个营地在另一个部落控制范围内。
    现在,向往核平的第二个部落首领决定搬迁避免战争,具体的,他会确定一个向量,所有营地平移这个向量。
    他给出了 \(Q\) 个方案,他想问你每个方案能否成功避免战争。

    Solution.

    首先,我们考虑这个平移,会让我们想到闵可夫斯基和。
    但是闵可夫斯基和是两个凸包之间的关系。
    我们考虑 \(B+\vec p=B'\Leftrightarrow A\),是不是可以直接认为 \(\vec p\Leftrightarrow A-B\)
    然后我们设 \(-B\) 等于 \(B\) 坐标取反后得到的凸包。
    然后判断 \(\vec p\) 是否在 \(A+(-B)\) 内即可。

    Coding.

    点击查看弱小代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),bz=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) bz=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	bz?x=-x:x;
    }/*}}}*/
    int n,m,Q,tt,CX[200005];
    struct Vec
    {
    	ll x,y;
    	inline Vec operator+(Vec b) const {return(Vec){x+b.x,y+b.y};}
    	inline Vec operator-(Vec b) const {return(Vec){x-b.x,y-b.y};}
    	inline ll operator^(Vec b) const {return x*b.x+y*b.y;}
    	inline ll operator*(Vec b) const {return x*b.y-y*b.x;}
    	inline ll dis() {return x*x+y*y;}
    }a[200005],b[200005],r[200005],v1[200005],v2[200005];
    inline char cmp(Vec a,Vec b) {return a*b>0||(a*b==0&&a.dis()<b.dis());}
    inline void convex(int &n,Vec *a)
    {
    	int tp=0;sort(a+1,a+n+1,[](Vec a,Vec b){return fabs(a.y-b.y)<1e-8?a.x<b.x:a.y<b.y;});
    	Vec bas=a[1];CX[tp=1]=1;for(int i=1;i<=n;i++) a[i]=a[i]-bas;
    	sort(a+2,a+n+1,cmp);for(int i=2;i<=n;CX[++tp]=i++)
    		while(tp>1&&(a[i]-a[CX[tp-1]])*(a[CX[tp]]-a[CX[tp-1]])>=0) tp--;
    	for(int i=1;i<=tp;i++) a[i]=a[CX[i]]+bas;
    	n=tp,a[n+1]=a[1];
    }
    inline void solve()
    {
    	v1[n]=a[1]-a[n];for(int i=1;i<n;i++) v1[i]=a[i+1]-a[i];
    	v2[m]=b[1]-b[m];for(int i=1;i<m;i++) v2[i]=b[i+1]-b[i];
    	int w1=1,w2=1;r[tt=1]=a[1]+b[1];
    	while(w1<=n&&w2<=m) ++tt,r[tt]=r[tt-1]+(v1[w1]*v2[w2]>=0?v1[w1++]:v2[w2++]);
    	while(w1<=n) ++tt,r[tt]=r[tt-1]+v1[w1++];
    	while(w2<=m) ++tt,r[tt]=r[tt-1]+v2[w2++];
    }
    inline char chk(Vec a)
    {
    	if(a*r[1]>0||r[tt]*a>0) return 0;
    	int wh=lower_bound(r+1,r+tt+1,a,cmp)-r-1;
    	return (a-r[wh])*(r[wh%tt+1]-r[wh])<=0;
    }
    int main()
    {
    	read(n),read(m),read(Q);Vec base,in;
    	for(int i=1;i<=n;i++) read(a[i].x),read(a[i].y);
    	for(int i=1;i<=m;i++) read(b[i].x),read(b[i].y),b[i].x=-b[i].x,b[i].y=-b[i].y;
    	convex(n,a),convex(m,b),solve(),convex(tt,r);
    	base=r[1];for(int i=tt;i>=1;i--) r[i]=r[i]-r[1];
    	while(Q--) read(in.x),read(in.y),printf("%d\n",chk(in-base));
    	return 0;
    }
    
  • 相关阅读:
    R语言实战
    Python Google Translate API
    Windows使用技巧
    test_CSDN_markdown_format
    Linux: bash script
    test_markdown
    线性基学习笔记+模板总结
    Educational Codeforces Round 69 D Yet Another Subarray Problem
    图片托管
    二维线段树模板,建树,维护最大最小值
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15150194.html
Copyright © 2011-2022 走看看