Angle Beats Gym - 102361A(计算几何)
Angle Beats
\]
题意
给出 \(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;
}
Angle Beats Gym - 102361A(计算几何)的更多相关文章
- Angle Beats Gym - 102361A
题目链接:https://vjudge.net/problem/Gym-102361A 题意:给定N个点,q次询问每次询问给一个点,问在N个点中取2个和给定点最多可以组成几个直角三角形. 思路:htt ...
- Gym102361A Angle Beats(直角三角形 计算几何)题解
题意: \(n\)个点,\(q\)个询问,每次问包含询问点的直角三角形有几个 思路: 代码: #include<bits/stdc++.h> using namespace std; co ...
- Codeforces Gym 102361A Angle Beats CCPC2019秦皇岛A题 题解
题目链接:https://codeforces.com/gym/102361/problem/A 题意:给定二维平面上的\(n\)个点,\(q\)次询问,每次加入一个点,询问平面上有几个包含该点的直角 ...
- hdu6731 Angle Beats(ccpc秦皇岛A,计算几何)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6731 题意: 给出$n$个点,有$q$次询问 每次询问给出一个点$b$,求这$n+1$个点,组成直角 ...
- Gym 101055A 计算几何,暴力
http://codeforces.com/gym/101055/problem/A 题目:给定一些三维空间的点,要你找一个平面,能覆盖尽量多的点,只要求输出点数即可.n<=50 因为数据量小, ...
- Rasheda And The Zeriba Gym - 100283A 计算几何
http://codeforces.com/gym/100283/problem/A 考虑到多边形是不稳定的,是可以变来变去的. 那么总是可以把每个点放到圆上. 所以只需要判断圆心角是不是小于等于36 ...
- 【HDOJ6731】Angle Beats(极角排序)
题意:二维平面上给定n个整点,q个询问 每个询问给定另外的一个整点,问其能与n个整点中任意取2个组成的直角三角形的个数 保证所有点位置不同 n<=2e3,q<=2e3,abs(x[i],y ...
- Gym - 101845D 计算几何
Ignacio is a famous mathematician, some time ago he was married with Dolly, a famous scientific, at ...
- CCPC 2019 秦皇岛 Angle Beats
题目 给出P个点,然后给出Q个询问,问从P中选出两个点和给的点能组成直角三角形的方法个数.-O2,时间限制5秒. \[2\leqslant P\leqslant 2000,\qquad 1\leqsl ...
随机推荐
- jenkins+sonarqube进行代码质量检测
JavaNeverGiveUp教程篇 用jenkins+sonarqube去检查代码是非常方便的,它能检查出代码中可能存在的一些问题,比如io流未关闭.空指针异常.死循环.代码不规范等问题. 1. 搭 ...
- 【linux】lvm扩展根分区
lvm扩展根目录 1.lvm的基本概念 physical volume (PV) 通常是一快硬盘.相当于一个物理设备,磁盘空间物理卷PV. volume group (VG) 相当于LVM的卷组,属于 ...
- Aladdin and the Flying Carpet LightOJ 1341 唯一分解定理
题意:给出a,b,问有多少种长方形满足面积为a,最短边>=b? 首先简单讲一下唯一分解定理. 唯一分解定理:任何一个自然数N,都可以满足:,pi是质数. 且N的正因子个数为(1+a1)*(1+a ...
- WPF XAML Trigger中使用动画后 动画对象冻结的处理办法
在编写XAML时 在Trigger中使用动画,在动画之后,动画对象就会被冻结,无法被其他动画或者属性改变. 处理办法有: 1 使用附加属性来添加动画 public static readonly De ...
- R数据挖掘 第一篇:聚类分析(划分)
聚类是把一个数据集划分成多个子集的过程,每一个子集称作一个簇(Cluster),聚类使得簇内的对象具有很高的相似性,但与其他簇中的对象很不相似,由聚类分析产生的簇的集合称作一个聚类.在相同的数据集上, ...
- PHP小程序后端支付代码亲测可用
小程序后端支付代码亲测可用 <?php namespace Home\Controller; use Think\Controller; class WechatpayController ex ...
- Entity Framework 学习系列(4) - EF 增删改
目录 写在前面 一.开发环境 二.创建项目 三.新增 1.单表新增 2.批量新增 3.多表新增 四.编辑 1.先查询,后编辑 2.创建实体,后编辑 五.删除 写在前面 在上一小节中,学习了如何 通过C ...
- MVC里模型常用的一些操作
学习也是做买卖,归根到底还是学习成本的问题. 下面把微软集合类型的增删改查稍微罗列一下,大家看看它能带来的便利,和你要学的新东西,还有风险(纯粹的数据操作,不用框架,风险其实不大)相比,是否值得.来决 ...
- centos7 配置nginx vim语法高亮
看了Nginx核心知识100讲,按照他的做法,没有配置成功,可以使用下面的方法: 下载nginx源码,http://nginx.org/en/download.html 这里下载的是:nginx-1. ...
- RESTful规范总结
思维导图xmind文件:https://files-cdn.cnblogs.com/files/benjieming/RESTful%E8%A7%84%E8%8C%83.zip