Angle Beats Gym - 102361A(计算几何)
时间:2019-10-07
本文章向大家介绍Angle Beats Gym - 102361A(计算几何),主要包括Angle Beats Gym - 102361A(计算几何)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Angle Beats
\[ Time Limit: 4000 ms \quad Memory Limit: 1048576 kB \]
题意
给出 \(n\) 个初始点以及 \(q\) 次询问,每次询问给出一个询问点 \(Q\),求包括 \(Q\) 点的直角三角形有多少个。保证 \(n+q\) 个点都不重复。
思路
- 对于每次询问,当 \(Q\) 为直角点时,以 \(Q\) 为原点,对 \(n\) 个点做象限极角排序,然后用双指针 \(L\)、 \(R\) 维护直角三角形的个数。 \(L\) 指针用来枚举其中的一条直角边, \(R\) 指针用来寻找在另一条直角边上的点有多少个,每次找 \(QL\) 这条边逆时针方向的另一条边\(QR\)。所以当 \(L\) 往逆时针转动时,\(R\) 也会往逆时针转动,那么就可以用双指针直接维护出来了,特别注意一下多个点在同一条直线上的情况就可以了。
- 若 \(Q\) 不是直角点时,可以离线处理,把 \(n+q\) 个点全部存出来,然后枚举以 \(n\) 个初始点为直角点时,对哪些的 \(Q\) 点有贡献,维护方法同上。
最后的复杂度为 \(O\left(qnC_1 + n(n+q)C_2\right)\),\(C_1、C_2\) 取决于在枚举直角点为原点后,到原点在同一条直线上的点数量。
我试过把 \(n+q\) 个节点全部提取出来,然后暴力枚举每个点为直角点的情况,但是这样复杂度会 \(T\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e4+10;
struct Point {
ll x, y;
int id;
} p[maxn], be[maxn];
int n, m;
int ans[maxn];
int cmp1(Point a, Point b) {
ll d = a.x*b.y - b.x*a.y;
if(d == 0) {
return a.x<b.x;
} else {
return d>0;
}
}
int Qua(Point a) {
if(a.x>0 && a.y>=0) return 1;
if(a.x<=0 && a.y>0) return 2;
if(a.x<0 && a.y<=0) return 3;
if(a.x>=0 && a.y<0) return 4;
}
int cmp(Point a, Point b) {
if(Qua(a) == Qua(b)) return cmp1(a, b);
else return Qua(a)<Qua(b);
}
ll check(Point a, Point b) {
return a.x*b.x + a.y*b.y;
}
ll chaji(Point a, Point b) {
return a.x*b.y - b.x*a.y;
}
ll work(Point pp) {
for(int i=1; i<=n; i++) {
p[i] = be[i];
p[i].x -= pp.x;
p[i].y -= pp.y;
}
p[0] = pp;
sort(p+1, p+1+n, cmp);
for(int j=1; j<=n; j++) {
p[j+n] = p[j];
}
ll ans = 0;
int R = 2;
for(int L=1; L<=n; L++) {
while(R<=2*n) {
if(chaji(p[L], p[R]) < 0) break;
if(check(p[L], p[R]) <= 0) break;
R++;
}
int tR = R;
while(tR<=2*n) {
if(chaji(p[L], p[tR]) <= 0) break;
if(check(p[L], p[tR]) != 0) break;
ans++;
tR++;
}
}
return ans;
}
int main(){
// freopen("in", "r", stdin);
while(~scanf("%d%d", &n, &m)) {
int all = 0;
for(int i=1; i<=n; i++) {
all++;
int x, y;
scanf("%d%d", &x, &y);
p[all].x = x, p[all].y = y, p[all].id = 0;
be[all] = p[all];
}
for(int i=1; i<=m; i++) {
all++;
int x, y;
scanf("%d%d", &x, &y);
p[all].x = x, p[all].y = y, p[all].id = i;
be[all] = p[all];
ans[i] = work(p[all]);
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=all; j++) {
p[j] = be[j];
}
p[0] = be[i];
int flag = 0;
for(int j=1; j<=all; j++) {
if(p[j].x == p[0].x && p[j].y == p[0].y) flag = 1;
if(flag) p[j] = p[j+1];
p[j].x -= p[0].x;
p[j].y -= p[0].y;
}
int nn = all-1;
sort(p+1, p+1+nn, cmp);
for(int j=1; j<=nn; j++) {
p[j+nn] = p[j];
}
int R = 2;
for(int L=1; L<=nn; L++) {
int id = 0;
if(p[0].id) id = p[0].id;
if(p[L].id) id = p[L].id;
while(R<=2*nn) {
if(chaji(p[L], p[R]) < 0) break;
if(check(p[L], p[R]) <= 0) break;
R++;
}
int tR = R;
while(tR<=2*nn) {
if(chaji(p[L], p[tR]) <= 0) break;
if(check(p[L], p[tR]) != 0) break;
if(id == 0) {
if(p[tR].id) ans[p[tR].id]++;
} else {
if(p[tR].id == 0) ans[id]++;
}
tR++;
}
}
}
for(int i=1; i<=m; i++) {
printf("%d\n", ans[i]);
}
}
return 0;
}
原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/11631203.html
- 最全爬虫攻略:微博、APP、公众号一个不能少!
- 注册中心 Eureka 源码解析 —— Eureka-Client 初始化(一)之 EurekaInstanceConfig
- 无论人工智能发展到什么地步,都离不开这6段代码
- Dubbo源码解析 —— 逻辑层设计之服务降级
- 【死磕Java并发】-----J.U.C之Condition
- 数据库中间件 MyCAT 源码分析 —— 【单库单表】查询
- 数据库中间件 MyCAT源码分析:【单库单表】插入
- 数据库中间件 MyCAT 源码分析 —— 调试环境搭建
- 分布式事务 TCC-Transaction 源码解析 —— 事务存储器
- 注册中心 Eureka 源码解析 —— 调试环境搭建
- 一样的代码、不一样的写法,JavaScript必知的简写技巧|附源代码
- 【死磕Java并发】-----J.U.C之读写锁:ReentrantReadWriteLock
- 数据库中间件 MyCAT源码分析——跨库两表Join
- iOS一种动态栅格布局方案
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- @JsonCreator自定义反序列化函数-JSON框架Jackson精解第5篇
- 不靠谱的 console
- 使用ThreadLocal和ArgumentResolver方便开发
- 【Java8新特性】05 使用Optional取代null
- 在不被spring容器管理的类中使用ApplicationContext应用上下文bean
- Spring boot 在静态类中注入spring组件
- Spring boot 自定义配置文件
- 数据分析 常见技巧和经验总结
- Go by Example 中文版: Base64 编码
- Django3.0+supervisor+uvicorn+nginx进行线上部署
- 前端杂货铺上新
- 短视频系统源代码,实现前置摄像头水平翻转
- linux配置SOCK5代理
- 前端踩坑系列《五》
- linux上安装mitmproxy