CCPC 2019 秦皇岛 Angle Beats
题目
给出P个点,然后给出Q个询问,问从P中选出两个点和给的点能组成直角三角形的方法个数。-O2,时间限制5秒。
\[2\leqslant P\leqslant 2000,\qquad 1\leqslant Q\leqslant2000\]
\[\left\lvert x_i\right\rvert \leqslant 10^9,\left\lvert y_i\right\rvert \leqslant 10^9\]
题解
卡常数的题目……刚开始想了个$n^2\times q$的做法= =显然过不了
稍微思考就分别以P个点和Q个点为中心对P个点进行极角排序,然后分两种情况(注意Q的位置)
1、
2、
对于1,可以枚举每一条与Q相连的边,然后顺时针寻找和这条边垂直的,类似于旋转卡壳,两个垂直的边会同时旋转,虽然极角排序需要$\mathcal{O}(n\log n)$的时间,二分和这个比起来在渐进意义上没有改变,但是因为要卡常,所以能减少一点是一点= =
对于2,可以预处理出以P个点为中心的极角排序,然后看和Q相连的边,找直角……(可以思考下如果找到A怎么办233(反正也不会重复,找到了也没事))
那么1可以$q\times n\log n+q\times n$
2可以$q\times q \log n$
因为要卡常,还需要很多技巧。
需要充分利用CPU的缓存,经常用的数据要放在一起,如果B要A的数据,C要B的数据,AAABBBCCC地做会比ABCABCABC慢,寄存快于缓存,缓存快于内存= =虽然用什么都是系统和编译器决定的,但是只有尽量放一起才能命中缓存。
对于2,$AB$和$BA'$两个垂直其实只用考虑斜率,那么在排序的时候就不用管象限了。
极角排序还是可以用斜率的,排序起来比叉乘快得多……而且比较大小也不必要非要按照分数的大小关系,只要保持有序就可以二分统计数字,这样就可以化为最简以后直接排序。
除了排序还可以将斜率进行HASH,unordered_map就可以用
(其实上面两种技巧我一个都不会= =看别人的代码卡过的)
AC代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
#define REP(i,a,b) for(register int i=(a);i<(b);i++)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) (void)0
#endif // LOCAL
#define D Point
#define CD const D
struct Point {
long long x,y;
int k;
};
inline bool operator<(CD&l, CD&r) {
return l.x<r.x || (l.x==r.x && l.y<r.y);
}
inline D operator-(D a, D b) {
return (D){a.x-b.x, a.y-b.y};
}
#define dot(a, b) (a.x*b.x+a.y*b.y)
#define cross(a,b) (a.x*b.y-a.y*b.x)
inline int qquad(D 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;
return 4;
}
inline bool cmp(D l, D r) {
if(l.k==r.k) {return cross(l,r)>0LL;}
return l.k<r.k;
}
const int T[]={0,3,4,1,2};
const int TT[]={0,2,3,4,1};
inline D rotCCW(D p) {return (D){-p.y,p.x,TT[p.k]};}
#undef D
#undef CD
#define LL long long
template<class T>
inline void read(T&x) {
x=0; int f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
x*=f;
}
inline LL gcd(LL a, LL b) {
return b==0?a:gcd(b,a%b);
}
Point P[2007],A[2007];
Point Z[2007];
Point zi[2007*2];
inline int findge(Point *t, int l, int r, Point k) {
while(l<r) {
int m=l+r>>1;
if(t[m]<k) l=m+1;
else r=m;
}
return l;
}
inline int findg(Point *t, int l, int r, Point k) {
while(l<r) {
int m=l+r>>1;
if(k<t[m]) r=m;
else l=m+1;
}
return l;
}
int aaa[2007];
int main() {
int n,q; read(n); read(q);
REP(i,0,n) {
read(P[i].x); read(P[i].y);
}
REP(i,0,q) {
read(A[i].x); read(A[i].y);
}
REP(i,0,q){
REP(j,0,n) {
zi[j]=P[j]-A[i];
zi[j].k=qquad(zi[j]);
}
sort(zi,zi+n,cmp);
REP(j,0,n) zi[j+n]=zi[j];
for(register int j=0,k=0,l=0,m=0; j<n;) {
for(; k<j+n && cross(zi[j],zi[k])==0 && dot(zi[j],zi[k])>0; k++);
for(l=max(k,m); l<j+n && cross(zi[j],zi[l])>0 && dot(zi[j],zi[l])>0; l++);
for(m=max(m,l); m<j+n && cross(zi[j],zi[m])>0 && dot(zi[j],zi[m])==0; m++);
aaa[i]+=(k-j)*(m-l);
j=k;
}
}
REP(j,0,n) {
int p=0;
REP(k,0,n) if(k!=j) {
Z[p]=P[k]-P[j];
Z[p].k=qquad(Z[p]);
LL g=gcd(Z[p].x,Z[p].y);
Z[p].x/=g, Z[p].y/=g;
if(Z[p].x<0) Z[p].x*=-1, Z[p].y*=-1;
p++;
}
sort(Z,Z+p); REP(i,0,q) {
Point z;
Point *L, *R;
z=P[j]-A[i];
int t=-z.y;
z.y=z.x; z.x=t; LL g=gcd(z.x,z.y);
z.x/=g, z.y/=g;
if(z.x<0) z.x=-z.x, z.y=-z.y; aaa[i]+=findg(Z,0,n-1,z)-findge(Z,0,n-1,z);
} //DBG("~~~%d\n", aaa[i]);
}
REP(i,0,q) printf("%d\n", aaa[i]); return 0;
}
对了就能拿银(快哭了)
CCPC 2019 秦皇岛 Angle Beats的更多相关文章
- Angle Beats Gym - 102361A(计算几何)
Angle Beats \[ Time Limit: 4000 ms \quad Memory Limit: 1048576 kB \] 题意 给出 \(n\) 个初始点以及 \(q\) 次询问,每次 ...
- hdu6731 Angle Beats(ccpc秦皇岛A,计算几何)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6731 题意: 给出$n$个点,有$q$次询问 每次询问给出一个点$b$,求这$n+1$个点,组成直角 ...
- 2019 秦皇岛CCPC赛后总结
以前一直想参加ICPC或CCPC的,所以即使得知比赛会打星号,我还是想去. 感觉自己对什么都没有兴趣了,比较渴望找点快乐.. 这场比赛非常强,吉老师和杜老师都来啦,还有岛娘! 有幸要到了签名 滚榜的时 ...
- Codeforces Gym 102361A Angle Beats CCPC2019秦皇岛A题 题解
题目链接:https://codeforces.com/gym/102361/problem/A 题意:给定二维平面上的\(n\)个点,\(q\)次询问,每次加入一个点,询问平面上有几个包含该点的直角 ...
- Gym102361A Angle Beats(直角三角形 计算几何)题解
题意: \(n\)个点,\(q\)个询问,每次问包含询问点的直角三角形有几个 思路: 代码: #include<bits/stdc++.h> using namespace std; co ...
- 【HDOJ6731】Angle Beats(极角排序)
题意:二维平面上给定n个整点,q个询问 每个询问给定另外的一个整点,问其能与n个整点中任意取2个组成的直角三角形的个数 保证所有点位置不同 n<=2e3,q<=2e3,abs(x[i],y ...
- CCPC 2019 网络赛 1006 Shuffle Card
// 签到题,比赛时候写双向链表debug了半天,发现有更好方法,记录一下. Shuffle Card HDU 6707 题意: 有一 \(n\) 张卡片,编号 \(1~n\) ,给定初始编号 ...
- CCPC 2019 网络赛 1002 array (权值线段树)
HDU 6703 array 题意: 给定一个数组 \(a_1,a_2, a_3,...a_n\) ,满足 \(1 \le a[i]\le n\) 且 \(a[i]\) 互不相同. 有两种 ...
- CCPC 2019 网络赛 HDU huntian oy (杜教筛)
1005 huntian oy (HDU 6706) 题意: 令,有T次询问,求 f(n, a, b). 其中 T = 10^4,1 <= n,a,b <= 1e9,保证每次 a,b互质. ...
随机推荐
- linux-touch 、mkdir、rm、pwd、which、locate、whatis
1.touch: 创建空文件,修改文件时间戳信息 atime(access time):最近访问文件内容时间 mtime(modify time):最近修改文件内容时间 ctime(change ti ...
- 【重温基础】instanceof运算符
最近开始在整理ES6/ES7/ES8/ES9的知识点(已经上传到 我的博客 上),碰到一些知识点是自己已经忘记(用得少的知识点),于是也重新复习了一遍. 这篇文章要复习的 instanceof 是我在 ...
- 修改element-ui默认属性
修改element ui默认的样式 如果要组件内全局修改 首先在浏览器里F12找到element默认的UI类名 找到要修改的默认类名以后 在文件中修改代码,重写属性 <style> .el ...
- 据说60%的Java程序员不明白分布式一致性?这次彻底搞懂!
前言 在计算机科学领域,分布式一致性是一个相当重要且被广泛探索与论证问题,首先来看三种业务场景. 1.火车站售票 假如说我们的终端用户是一位经常坐火车的旅行家,通常他是去车站的售票处购买车票,然后拿着 ...
- 搭建react native所遇到的坑
一.所遇问题 在搭建react native环境中,遇到执行react native run-android命令出现如下问题 Could not resolve all dependencies f ...
- dev gridcontrol 行号
/// <summary> /// GridView 显示行号 设置行号列的宽度 /// </summary> /// <param name="gv" ...
- win10: 搭建FTP服务器
新建用户,可以设置多个用户,给予不同的权限 ftp创建完成后,新用户创建完成后,我们回到计算机管理-Internet Information Services(IIS)管理器来管理我们的FTP站点,点 ...
- aspnet boilerplate 随笔一
使用abp模板进行项目开发: 1:准备工作:我使用v2.x版本,所以会依赖.net core 2.2 查看并更新本地环境: 更新.net core版本:cmd 运行 dotnet --version查 ...
- Linux重器之 Vim 实用命令
Vim 常用的命令 光标定位; hjkl 上下左右移动 0 $ 跳到行首或行尾 gg shift+G 跳到整个文件的开头行或者结尾行 1G ,2G,3G........NG ,跳到第1.2.3 ...
- cinder安装与配置
cinder是openstack中提供块存储服务的组件,主要是为虚拟机实例提供虚拟磁盘. 通过某种协议(SAS,SCSI,SAN,iSCSI等)挂接裸硬盘,然后分区.格式化创建的文件,或者直接使用裸硬 ...