题目大意:
给出
n(n≤105)
个点的凸包以及另外
m(m≤105)
个点,以及一个不大于
m
的非负整数
分析:
想了半天才想到是扫描线…
把所有的点排序,从左往右扫,记录当前扫描线处的凸包上下界限,判断点是否在这个范围内即可。
AC code:
#include <cstdio>
#include <cmath>
#include <map>
#include <algorithm>
#define cx first
#define cy second
#define mp make_pair
#define eps 1e-8
#define is_zero(p) ((p) >= -eps && (p) <= eps)
typedef double DB;
using namespace std;
const int MAXN = 1e5+9;
const int MAXM = 1e5+9;
int n, m, k;
map< pair<int,int>,int > Map;
struct pot
{
DB x, y;
pot(DB tx=0, DB ty=0):x(tx),y(ty){}
friend bool operator < (const pot &a, const pot &b)
{
return a.x < b.x-eps || (is_zero(a.x-b.x) && a.y < b.y-eps);
}
}cvx[MAXN], other[MAXN];
int pre[MAXN][2], suf[MAXN][2];
pair<pot, int> node[MAXN+MAXM];
int sign(DB x)
{
if(x < -eps) return -1;
else return x > eps;
}
DB fx(const pot &a, const pot &b, DB p)
{
DB ret;
if(is_zero(b.x-a.x)) return 1e10;
ret = (p-a.x)/(b.x-a.x)*(b.y-a.y)+a.y;
return ret;
}
void make_pre(int l, int r)
{
int now = r;
while(now != l)
{
pre[now][0] = now%n+1;
suf[now%n+1][0] = now;
now = now%n+1;
}
now = r;
while(now != l)
{
pre[now][1] = (now-2+n)%n+1;
suf[(now-2+n)%n+1][1] = now;
now = (now-2+n)%n+1;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
scanf("%d%d%d", &n, &m, &k);
int ru = 0, ld = 0, tot = 0;
for(int i = 1; i <= n; ++i)
{
int x, y;
scanf("%d%d", &x, &y);
cvx[i] = pot(x, y);
node[++tot] = mp(cvx[i], i);
Map[mp(x, y)] = i;
if(!ru || cvx[ru] < cvx[i]) ru = i;
if(!ld || cvx[i] < cvx[ld]) ld = i;
}
make_pre(ld, ru);
int sum = 0;
for(int i = 1; i <= m; ++i)
{
int x, y;
scanf("%d%d", &x, &y);
other[i] = pot(x, y);
if(Map.find(mp(x, y)) != Map.end()) sum++;
else node[++tot] = mp(other[i], 0);
}
sort(node+1, node+n+m+1);
bool in = false;
int up, down;
for(int i = 1; i <= n+m; ++i)
{
int id = node[i].cy;
pot now = node[i].cx;
if(!id)
{
if(in)
{
DB h1 = fx(cvx[up], cvx[suf[up][0]], now.x), h2 = fx(cvx[down], cvx[suf[down][1]], now.x);
if(h1 > 1e9) {if(sign(cvx[suf[up][0]].y-now.y) >= 0) sum++;}
else if(h2 > 1e9) {if(sign(cvx[suf[down][1]].y-now.y) >= 0) sum++;}
else if(sign(now.y-h2) >= 0 && sign(h1-now.y) >= 0) sum++;
}
}
else
{
if(id == ld) in = true, up = down = id;
else
{
if(id == ru) break;
if(pre[id][0] == up) up = id;
else down = id;
}
}
}
if(sum >= k) puts("YES");
else puts("NO");
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}