题意:给n个大点,m个小点$(n<=1e5,m<=5e5),问有多少个小点,存在3个大点,使小点在三个大点组成的三角形内。

解题思路:

  首先,易证,若该小点在某三大点行成的三角形内,则该小点必然处在大点组成的凸包内。那么首先,现将大点形成的凸包计算出来,但是若对每个点进行暴力枚举,在最坏情况下,若凸包上点数太多并且脸黑不断找区间,复杂度会达到$O(nm)$,因此要对点是否在凸包内的判断过程进行优化。

  将凸包划分为若干个三角形,我们可以先将这m个待判断的点进行极角排序,排序后,极角较大的点要么处在较小的点的逆时针方向的三角形内要么在同一个三角形内,要么两个点在同一三角形内。因此在点坐标转移时,采用旋转卡壳,所在的三角形区域也逆时针选择即可。而对于小点是否在三角形内,采用面积判断即可,为了防止爆精度推荐用行列式计算面积,时间复杂度$O(nlogn+mlogm+m)$

  下面贴上AC代码。

  

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rept(i,a,b) for(int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof a)
#define pb push_back
#define dd(x) cout<<#x<<"="<<x<<" "
#define de(x) cout<<#x<<"="<<x<<"\n"
#define fi first
#define se second
#define mp make_pair
pii point[],small[];
pii operator -(const pii &s1,const pii &s2)
{
return mp(s1.fi-s2.fi,s1.se-s2.se);
}
int s[];
ll chaji(const pii &s1,const pii &s2)
{
return s1.fi*s2.se-s1.se*s2.fi;
}
bool comp(const pii &s1,const pii &s2)
{
if((s1.se<point[].se)+(s2.se<point[].se)==) return s1.se>s2.se;
ll x=chaji(s1-point[],s2-point[]);
if(x>||(x==&&abs(s1.fi-point[].fi)<abs(s2.fi-point[].fi))) return ;
else return ;
}
ll sqare(const pii &a,const pii &b,const pii &c)
{
return abs( (b.fi-a.fi)*(c.se-a.se) -(c.fi-a.fi)*(b.se-a.se) );
} int main()
{
ios::sync_with_stdio(false);
cin.tie();
int n,m;
cin>>n;
rep(i,,n) cin>>point[i].fi>>point[i].se;
int p=;
rep(i,,n)
if( point[i].se<point[p].se||(point[i].se==point[p].se&&point[i].fi<point[p].fi) )
p=i;
swap(point[],point[p]);
//dd(point[0].fi);de(point[0].se);
sort(point+,point+n,comp);
int cnt=;
s[cnt++]=;
s[cnt++]=; rep(i,,n)
{
while(cnt>=&&chaji(point[s[cnt-]]-point[i],point[s[cnt-]]-point[i])>=) cnt--;
s[cnt++]=i;
} cin>>m;
rep(i,,m) cin>>small[i].fi>>small[i].se;
sort(small,small+m,comp);
int ans=;
p=; int start=;
while(start<m&&chaji(small[start]-point[s[]],point[s[]]-point[s[]])>) start++;
rep(i,start,m)
{
if(small[i].se<point[].se) break;
while(p<cnt-&&chaji( small[i]-point[s[]],point[s[p+]]-point[s[]] )< ) p++;
if(p==cnt-) break;
if(chaji( small[i]-point[s[]],point[s[p]]-point[s[]] )== )
{
if((small[i].fi<point[s[]].fi)+(small[i].fi<point[s[p]].fi)==) ans++;
continue;
}
else if(chaji( small[i]-point[s[]],point[s[p+]]-point[s[]] )<)
{
if((small[i].fi<point[s[]].fi)+(small[i].fi<point[s[p+]].fi)==) ans++;
continue;
}
if(sqare(point[s[]],point[s[p]],point[s[p+]])==sqare(point[s[]],point[s[p]],small[i])+sqare(point[s[]],point[s[p+]],small[i])+sqare(point[s[p]],point[s[p+]],small[i]))
ans++;
}
cout<<ans<<endl;
return ;
}

15-16 ICPC europe J Saint John Festival (graham扫描法+旋转卡壳)的更多相关文章

  1. Saint John Festival Gym - 101128J (凸包二分)

    Problem J: Saint John Festival \[ Time Limit: 1 s \quad Memory Limit: 256 MiB \] 题意 给出\(n\)个大点,和\(m\ ...

  2. UVALive 7281 Saint John Festival (凸包+O(logn)判断点在凸多边形内)

    Saint John Festival 题目链接: http://acm.hust.edu.cn/vjudge/contest/127406#problem/J Description Porto's ...

  3. 【计算几何】【凸包】【极角排序】【二分】Gym - 101128J - Saint John Festival

    平面上n个红点,m个黑点,问你多少个黑点至少在一个红三角形内. 对红点求凸包后,转化为询问有多少个黑点在凸包内. 点在凸多边形内部判定,选定一个凸包上的点作原点,对凸包三角剖分,将其他的点极角排序之后 ...

  4. UVA - 13024 Saint John Festival 凸包+二分

    题目链接:https://vjudge.net/problem/UVA-13024 题意:先给出\(L\)个点构造一个凸包,再给出\(S\)个点,询问有几个点在凸包内. 题解:判断点是否在凸包内的模板 ...

  5. UVA 13024: Saint John Festival(凸包+二分 ,判定多个点在凸包内)

    题意:给定N个点,Q次询问,问当前点知否在N个点组成的凸包内. 思路:由于是凸包,我们可以利用二分求解. 二分思路1:求得上凸包和下凸包,那么两次二分,如果点在对应上凸包的下面,对应下凸包的上面,那么 ...

  6. Gym 101128J Saint John Festival(凸包 + 二分判点和凸包关系)题解

    题意:给你一堆黑点一堆红点,问你有最多几个黑点能找到三个红点,使这个黑点在三角形内? 思路:显然红点组成的凸包内的所有黑点都能做到.但是判断黑点和凸包的关系朴素方法使O(n^2),显然超时.那么我现在 ...

  7. Python Cookbook(第3版)中文版:15.16 不确定编码格式的C字符串

    15.16 不确定编码格式的C字符串¶ 问题¶ 你要在C和Python直接来回转换字符串,但是C中的编码格式并不确定. 例如,可能C中的数据期望是UTF-8,但是并没有强制它必须是. 你想编写代码来以 ...

  8. 剑指offer19:按照从外向里以顺时针的顺序依次打印出每一个数字,4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

    1 题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印 ...

  9. linux 学习15 16 启动管理,备份和恢复

    第十五讲 启动管理 . CentOS .x 启动管理 //此处指6.3 系统运行级别 .运行级别 运行级别 含 义 关机 单用户模式,可以想象为windows的安全模式,主要用于系统修复 //linu ...

随机推荐

  1. Kafka(三) —— 集群监控

    任何应用功能再强大.性能再优越,如果没有与之匹配的监控,那么一切都是虚无缥缈的.监控不仅可以为应用提供运行时的数据作为依据参考,还可以迅速定位问题,提供预防及告警等功能,很大程度上增强了整体服务的鲁棒 ...

  2. Mac和window生成ssh和查看ssh key

    一.MAC系统 mac 系统开始就已经为我们安装了ssh 如果没有安装,首先安装 打开终端:$ ssh -v 查看ssh版本 OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec ...

  3. Spark(五十二):Spark Scheduler模块之DAGScheduler流程

    导入 从一个Job运行过程中来看DAGScheduler是运行在Driver端的,其工作流程如下图: 图中涉及到的词汇概念: 1. RDD——Resillient Distributed Datase ...

  4. Faster async functions and promises

    https://v8.dev/blog/fast-async async function computeAnswer() { return 42;}undefinedconst p = comput ...

  5. MXNet/Gluon 中网络和参数的存取方式

    https://blog.csdn.net/caroline_wendy/article/details/80494120 Gluon是MXNet的高层封装,网络设计简单易用,与Keras类似.随着深 ...

  6. 小D课堂 - 零基础入门SpringBoot2.X到实战_第10节 SpringBoot整合定时任务和异步任务处理_41、SpringBoot定时任务schedule讲解

    笔记 1.SpringBoot定时任务schedule讲解     简介:讲解什么是定时任务和常见定时任务区别 1.常见定时任务 Java自带的java.util.Timer类            ...

  7. openresty开发系列26--openresty中使用redis模块

    openresty开发系列26--openresty中使用redis模块 在一些高并发的场景中,我们常常会用到缓存技术,现在我们常用的分布式缓存redis是最知名的, 操作redis,我们需要引入re ...

  8. 使用kindeditor获取不到富文本框中的值

    获取不到富文本框中的值,网上一搜一堆,但最终没有几个能解决问题的,折腾一番最终解决.注意就是红色代码,加上之后就可以解决问题了. KindEditor.ready(function (K) { var ...

  9. Microsoft VBScript 运行时错误 错误 800a005e 无效使用 Null: Replace

    查看数据库   表的字段里面是否有空的字段. where 字段名 is null

  10. QCamera检测摄像头

    The QCamera class provides interface for system camera devices. More... Header: #include <QCamera ...