当前位置: 首页 > news >正文

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

题意:给你一堆黑点一堆红点,问你有最多几个黑点能找到三个红点,使这个黑点在三角形内?

思路:显然红点组成的凸包内的所有黑点都能做到。但是判断黑点和凸包的关系朴素方法使O(n^2),显然超时。那么我现在有一个更好的方法判断点和凸包的关系。我固定一个红点,然后找连续两个红点使黑点 i 在这个三角形内(向量判),然后用二分查找是否存在这样的两个连续红点。这样复杂度为nlogn。

注意凸包不要用atan2的那种,会有精度误差...

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e4 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
struct point
{
    double x,y;
}p[100000],a[100000],b[100000], g;
int n, tot;
bool cmp(point A,point B)
{
    if(A.x!=B.x)
    return A.x<B.x;
    return A.y<B.y;
}
point operator -(point A,point B)
{
    point c;
    c.x=A.x-B.x;
    c.y=A.y-B.y;
    return c;
}
double cross(point A,point B)
{
    return A.x*B.y-B.x*A.y;
}
void dopack()
{
    tot=0;
    for(int i=1;i<=n;i++)
    {
        while(tot>1&&cross(p[tot-1]-p[tot-2],a[i]-p[tot-2])<=0)tot--;
        p[tot++]=a[i];
    }
    int k=tot;
    for(int i=n-1;i>0;i--)
    {
        while(tot>k&&cross(p[tot-1]-p[tot-2],a[i]-p[tot-2])<=0)tot--;
        p[tot++]=a[i];
    }
    if(n>1)tot--;
}
double turn(point st, point en, point q){
    //正数:点在向量左侧
    //负数:点在向量右侧
    //0:点在向量直线上
    return (st.x - q.x) * (en.y - q.y) - (en.x - q.x) * (st.y - q.y);
}
int mid(){
    int l, r;
    l = 1, r = tot - 2;
    while(l <= r){
        int m = (l + r) >> 1;
        if(turn(p[0], p[m], g) >= 0 && turn(p[0], p[m + 1], g) <= 0){
            if(turn(p[m], p[m + 1], g) >= 0) return 1;
            return 0;
        }
        if(turn(p[0], p[m], g) >= 0){
            l = m + 1;
        }
        else{
            r = m - 1;
        }
    }
    return 0;
}
int main(){
    int m;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lf%lf", &a[i].x, &a[i].y);
    sort(a+1,a+1+n,cmp);
    dopack();
//    for(int i = 0; i < tot; i++){
//        printf("* %lf %lf\n", p[i].x, p[i].y);
//    }
    scanf("%d", &m);
    int ans = 0;
    for(int i = 1; i <= m; i++){
        scanf("%lf%lf", &g.x, &g.y);
        ans += mid();
    }
    printf("%d\n", ans);
    return 0;
}

 

转载于:https://www.cnblogs.com/KirinSB/p/10821551.html

相关文章:

  • chrome浏览器常用快捷键
  • openshift 使用curl命令访问apiserver
  • 服务器指示灯说明
  • 单兵虚拟训练仿真系统
  • css笔记04
  • Jmeter察看结果树的响应数据中的中文显示乱码问题处理
  • HTML5 details 标签
  • 重学前端-CSS篇3-颜色、单位、字体、命名规范、书写顺序
  • 递归与尾递归(C语言)
  • 面向对象-类与对象的定义和使用(包含init讲解)
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • Android进阶——Java注解实战之APT构建模块化的第一步
  • Android 仿微信, QQ 裁剪
  • 知名博客
  • JS时间比较大小
  • 《深入 React 技术栈》
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • Flex布局到底解决了什么问题
  • Git初体验
  • node 版本过低
  • PAT A1017 优先队列
  • Sequelize 中文文档 v4 - Getting started - 入门
  • Spring声明式事务管理之一:五大属性分析
  • TCP拥塞控制
  • Twitter赢在开放,三年创造奇迹
  • uva 10370 Above Average
  • vue-cli3搭建项目
  • Webpack 4x 之路 ( 四 )
  • 聊聊sentinel的DegradeSlot
  • 前嗅ForeSpider中数据浏览界面介绍
  • 驱动程序原理
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 入口文件开始,分析Vue源码实现
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 使用SAX解析XML
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • hi-nginx-1.3.4编译安装
  • ​queue --- 一个同步的队列类​
  • (175)FPGA门控时钟技术
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (done) 两个矩阵 “相似” 是什么意思?
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (十六)Flask之蓝图
  • (五)关系数据库标准语言SQL
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)基于IDEA的JAVA基础10
  • (一)基于IDEA的JAVA基础12
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)c++ std::pair 与 std::make
  • (转)创业家杂志:UCWEB天使第一步
  • .net 7 上传文件踩坑
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例