JSOI 2018 戰爭題解
阿新 • • 發佈:2020-12-17
JSOI2018 戰爭 題解
假設A部落佔領的點集為\(A\),B部落的為\(B\)。
則問題轉換成,給你一個向量\(v\)。判斷是否\(\exists a\in A,b+v=a,(b\in B)\)
則是否存在\(a-b=v\)
若我們可以處理出\(a-b\)的點集\(C\)。問題就轉換成查詢一個向量是否在一個凸包內。
我們將所有\(B\)中的點乘上\(-1\)。得到\(B'\)。
然後處理出向量\(A\)和\(B\)的閔科夫斯基和。關於閔科夫斯基和
可以得到一個大凸包。
然後取最下面的點(如果右多個就取最左面的)作為極點。將其它點極交排序。然後就可以用二分找到所屬於的三角形假設是\(\triangle ABO\)
注意:閔科夫斯基和一定要去除共線的點。
/* { ###################### # Author # # Gary # # 2020 # ###################### */ #include<bits/stdc++.h> #define rb(a,b,c) for(int a=b;a<=c;++a) #define rl(a,b,c) for(int a=b;a>=c;--a) #define LL long long #define IT iterator #define PB push_back #define II(a,b) make_pair(a,b) #define FIR first #define SEC second #define FREO freopen("check.out","w",stdout) #define rep(a,b) for(int a=0;a<b;++a) #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()) #define random(a) rng()%a #define ALL(a) a.begin(),a.end() #define POB pop_back #define ff fflush(stdout) #define fastio ios::sync_with_stdio(false) #define check_min(a,b) a=min(a,b) #define check_max(a,b) a=max(a,b) using namespace std; //inline int read(){ // int x=0; // char ch=getchar(); // while(ch<'0'||ch>'9'){ // ch=getchar(); // } // while(ch>='0'&&ch<='9'){ // x=(x<<1)+(x<<3)+(ch^48); // ch=getchar(); // } // return x; //} const double INF=1e18; typedef pair<int,int> mp; /*} */ const double pi=3.1415926535897932384626433832795; const double eps=1e-10; struct vec{ double x,y; vec(){} vec(double X,double Y){ x=X; y=Y; } bool operator < (vec oth){ if(x!=oth.x) return x<oth.x; return y<oth.y; } double operator * (vec oth){ return x*oth.y-oth.x*y; } vec operator - (vec oth){ return vec(x-oth.x,y-oth.y); } vec operator + (vec oth){ return vec(x+oth.x,y+oth.y); } bool operator != (vec oth){ return (abs(x-oth.x)>eps)||(abs(y-oth.y)>eps); } }; double angle(vec v){ if(v.y>=0){ if(abs(v.x)<=eps) return pi/2.0; if(v.x>eps){ return atan(v.y/v.x); } else return atan(v.y/v.x)+pi; } if(abs(v.x)<=eps) return pi/2.0+pi; if(v.x>eps){ return atan(v.y/v.x)+2.0*pi; } return atan(v.y/v.x)+pi; } bool cmp(vec A,vec B){ return angle(A)<angle(B); } vector<int> sta; bool used[200000+20]; struct convex_hull{ vector<vec> v; convex_hull(){} convex_hull(vector<vec> points){ memset(used,0,sizeof(used)); sta.clear(); sta.PB(0); sort(ALL(points)); rep(i,points.size()){ if(!i) continue; while(sta.size()>1&&(points[sta.back()]-points[sta[sta.size()-2]])*(points[i]-points[sta.back()])<=0){ used[sta.back()]=0; sta.POB(); } used[i]=1; sta.PB(i); } int tmp=sta.size(); rl(i,points.size()-1,0){ if(used[i]) continue; while(sta.size()>tmp&&(points[sta.back()]-points[sta[sta.size()-2]])*(points[i]-points[sta.back()])<=0) sta.POB(); sta.PB(i); } for(auto it:sta) v.PB(points[it]); v.POB(); } convex_hull operator + (convex_hull oth){ vec ma=vec(INF,INF),mb=vec(INF,INF); for(auto it:v){ if(it.y<ma.y){ ma=it; } else if(it.y==ma.y&&it.x<ma.x) ma=it; } for(auto it:oth.v){ if(it.y<mb.y){ mb=it; } else if(it.y==mb.y&&it.x<mb.x) mb=it; } ma=ma+mb; vector<vec> nv; rep(i,v.size()){ nv.PB(v[(i+1)%v.size()]-v[i]); } rep(i,oth.v.size()){ nv.PB(oth.v[(i+1)%oth.v.size()]-oth.v[i]); } sort(ALL(nv),cmp); convex_hull ret; vec now=vec(0,0); for(auto it:nv){ ret.v.PB(now); now=now+it; } for(auto & it:ret.v) it=it+ma; return ret; } vec get_polar_point(){ vec ret=vec(INF,INF); for(auto it:v){ if(it.y<ret.y) ret=it; else if(it.y==ret.y&&it.x<ret.x) ret=it; } return ret; } }; int main(){ int n,m,q; scanf("%d%d%d",&n,&m,&q); vector<vec> points; rb(i,1,n){ int x,y; scanf("%d%d",&x,&y); points.PB(vec(x,y)); } convex_hull A(points); points.clear(); rb(i,1,m){ int x,y; scanf("%d%d",&x,&y); x=-x; y=-y; points.PB(vec(x,y)); } convex_hull B(points); A=A+B; A=convex_hull(A.v); vec pp=A.get_polar_point(); for(auto &it:A.v){ it=it-pp; } vector<vec> oth; for(auto it:A.v){ if(it!=vec(0,0)){ oth.PB(it); } } sort(ALL(oth),cmp); rb(i,1,q){ int x,y; scanf("%d%d",&x,&y); vec query=vec(x,y); query=query-pp; bool ok=false; int is=upper_bound(ALL(oth),query,cmp)-oth.begin(); if(is==oth.size()){ if(abs(angle(oth.back())-angle(query))<=eps&&oth.back().x+eps>=query.x){ ok=true; } } else{ if(is!=0){ vec u,d; u=oth[is]; d=oth[is-1]; if((u-query)*(d-query)<=eps){ ok=true; } } else{ if(abs(angle(oth[0])-angle(query))<=eps&&oth[0].x+eps>=query.x){ ok=true; } } } printf("%d\n",ok); } return 0; }