平面上给你n(不超过2000)个点,问你能构成多少个面积在[A,B]之间的Rt三角形。

枚举每个点作为直角顶点,对其他点极角排序,同方向的按长度排序,然后依次枚举每个向量,与其对应的另一条直角边是单调的,可以用一个pointer做出来,然后可以得出那些同方向的向量的区间(这个代码好像有点问题,可能会退化,最好确定了一个LL之后,对一个方向的不要重复算RR。这里如果也改成二分就比较好,复杂度不会退化)。然后通过二分可以得到A使得面积在[A,B]间的有哪些(其实这个因为也是单调的,好像也没必要二分,不过二分也不影响)。

Hint:极角排序通过讨论所在象限以及叉积,可以避免使用atan2造成精度误差。atan2貌似只能处理坐标在几千内的情况。

O(n^2logn)

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll ans;
struct Point{
ll x,y;
int xx;
ll l;
Point(){}
Point(const ll &x,const ll &y){
this->x=x;
this->y=y;
}
void read(){
scanf("%lld%lld",&x,&y);
}
ll leng2(){
return x*x+y*y;
}
}a[2005],p[4005];
typedef Point Vector;
Vector operator - (const Point &a,const Point &b){
return Vector(a.x-b.x,a.y-b.y);
}
bool cmp(const Point &a,const Point &b){
if(a.xx!=b.xx){
return a.xx<b.xx;
}
if(a.x*b.y != a.y*b.x){
return a.x*b.y > a.y*b.x;
}
return a.l<b.l;
}
ll dot(const Vector &a,const Vector &b){
return a.x*b.x+a.y*b.y;
}
ll Abs(const ll &x){
return x<0 ? (-x) : x;
}
ll area(const Vector &a,const Vector &b){
return Abs(a.x*b.y-a.y*b.x);
}
ll Cross(const Vector &a,const Vector &b){
return a.x*b.y-a.y*b.x;
}
ll A,B;
int n,e;
int main(){
// freopen("j.in","r",stdin);
// freopen("j.out","w",stdout);
scanf("%d%lld%lld",&n,&A,&B);
for(int i=1;i<=n;++i){
a[i].read();
}
for(int i=1;i<=n;++i){
e=0;
for(int j=1;j<=n;++j){
if(j!=i){
p[++e]=a[j]-a[i];
if(p[e].x>0 && p[e].y>=0){
p[e].xx=1;
}
else if(p[e].x<=0 && p[e].y>0){
p[e].xx=2;
}
else if(p[e].x<0 && p[e].y<=0){
p[e].xx=3;
}
else{
p[e].xx=4;
}
p[e].l=p[e].leng2();
}
}
sort(p+1,p+e+1,cmp);
for(int j=e+1;j<=2*e;++j){
p[j]=p[j-e];
}
e<<=1;
int LL=1;
for(int j=1;j<=e/2;++j){
while(dot(p[LL],p[j])>0 && Cross(p[LL],p[j])<=0 && LL<j+e/2){
++LL;
}
if(dot(p[LL],p[j])!=0 || Cross(p[LL],p[j])>0){
continue;
}
int RR=LL;
while(Cross(p[RR],p[LL])==0 && dot(p[RR],p[LL])>0){
++RR;
}
if(RR>LL){
if(area(p[LL],p[j])<=2ll*A-1ll){
int l=LL,r=RR-1;
while(l<r){
int mid=(l+r+1>>1);
if(area(p[mid],p[j])<=2ll*A-1ll){
l=mid;
}
else{
r=mid-1;
}
}
ans-=(ll)(l-LL+1);
}
if(area(p[LL],p[j])<=2ll*B){
int l=LL,r=RR-1;
while(l<r){
int mid=(l+r+1>>1);
if(area(p[mid],p[j])<=2ll*B){
l=mid;
}
else{
r=mid-1;
}
}
ans+=(ll)(l-LL+1);
}
}
}
}
printf("%lld\n",ans);
return 0;
}

【计算几何】【极角排序】【二分】Petrozavodsk Summer Training Camp 2016 Day 6: Warsaw U Contest, XVI Open Cup Onsite, Sunday, August 28, 2016 Problem J. Triangles的更多相关文章

  1. 【线段树】Petrozavodsk Summer Training Camp 2016 Day 6: Warsaw U Contest, XVI Open Cup Onsite, Sunday, August 28, 2016 Problem H. Hay

    有一些草,一开始高度都是0,它们的生长速率不同. 给你一些单增的日期,在这些日期要将>b的草的部分都割掉,问你每次割掉的部分有多少. 将草的生长速率从大到小排序,这样每次割掉的是一个后缀,而且不 ...

  2. 【枚举】Petrozavodsk Summer Training Camp 2016 Day 6: Warsaw U Contest, XVI Open Cup Onsite, Sunday, August 28, 2016 Problem G. Equation

    f(n)定义为n的十进制表示下所有位的平方和. 问你方程K*f(n)=n在a<=n<=b中的解的个数. 发现f(n)最大不超过2000,可以直接枚举f(n),然后判断K*f(n)的位的平方 ...

  3. Petrozavodsk Summer-2016. Warsaw U Contest, XVI Open Cup Onsite.

    Petrozavodsk Summer-2016. Warsaw U Contest, XVI Open Cup Onsite. Problem A. Gambling Problem B. Colo ...

  4. 【动态规划】【二分】Petrozavodsk Winter Training Camp 2017 Day 1: Jagiellonian U Contest, Monday, January 30, 2017 Problem B. Dissertation

    题意: 给定S1串,长度100w,S2串,长度1k.问它俩的LCS. f(i,j)表示S2串前i个字符,LCS为j时,最少需要的S1串的前缀长度.转移的时候,枚举下一个字符在S1的位置即可.(可以预处 ...

  5. 【二分】Petrozavodsk Winter Training Camp 2017 Day 1: Jagiellonian U Contest, Monday, January 30, 2017 Problem A. The Catcher in the Rye

    一个区域,垂直分成三块,每块有一个速度限制,问你从左下角跑到右上角的最短时间. 将区域看作三块折射率不同的介质,可以证明,按照光路跑时间最短. 于是可以二分第一个入射角,此时可以推出射到最右侧边界上的 ...

  6. 【取对数】【哈希】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem J. Bobby Tables

    题意:给你一个大整数X的素因子分解形式,每个因子不超过m.问你能否找到两个数n,k,k<=n<=m,使得C(n,k)=X. 不妨取对数,把乘法转换成加法.枚举n,然后去找最大的k(< ...

  7. 【BFS】【最小生成树】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem G. We Need More Managers!

    题意:给你n个点,点带权,任意两点之间的边权是它们的点权的异或值中“1”的个数,问你该图的最小生成树. 看似是个完全图,实际上有很多边是废的.类似……卡诺图的思想?从读入的点出发BFS,每次只到改变它 ...

  8. 【状压dp】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem E. Guessing Game

    题意:给你n个两两不同的零一串,Alice在其中选定一个,Bob去猜,每次询问某一位是0 or 1.问你最坏情况下最少要猜几次. f(22...2)表示当前状态的最小步数,2表示这位没确定,1表示确定 ...

  9. 【推导】【单调性】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem B. Tribute

    题意:有n个数,除了空集外,它们会形成2^n-1个子集,给你这些子集的和的结果,让你还原原来的n个数. 假设原数是3 5 16, 那么它们形成3 5 8 16 19 21 24, 那么第一轮取出开头的 ...

随机推荐

  1. chrome表单自动填充导致input文本框背景变成偏黄色问题

    你曾遇到过吗? 困扰宝宝好久的问题,本以为是什么插件导致的,结果是chrome浏览器自动填充文本时默认的样式,搜嘎. 一.修改自动填充input文本框背景色: 使用以下代码 可以设置自己的想要的默认文 ...

  2. 9.1docker容器 跨主机连接

    open vswitch 实现跨主机容器连接          准备条件   将本地的网卡 与新建的网桥建立连接   配置 docker 启动项       weave实现跨主机容器连接   null

  3. 5.0docer 网络链接

    docker0 :linux的虚拟网桥 虚拟网桥特点: 1.可以设置ip地址 2.相当于拥一个隐藏的虚拟网卡     安装网桥工具 apt-get install bridge-utils brctl ...

  4. [Leetcode Week14]Maximum Binary Tree

    Maximum Binary Tree 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/maximum-binary-tree/description/ ...

  5. otg device id pin 探討

    Platform : Qualcomm MSM8937 PMIC : Qualcomm PMI8940 OTG base on USB2.0,增加 device 可當 host 也可當 periphe ...

  6. make command explaination 編譯命令解釋

    Creating .config file make ARCH=arm CROSS_COMPILE=arm-none-eabi- stm32_defconfig 以上命令是 將變數 ARCH=arm, ...

  7. 设计模式之笔记--桥接模式(Bridge)

    桥接模式(Bridge) 定义 桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化. 类图 描述 Abstraction:定义抽象部分的接口,通常在这个接口里面要维护一个实 ...

  8. OC 07 类的扩展

    1.NSDate的使用 NSDate是Cocoa中⽤于处理⽇期和时间的基础类,封装了某⼀给定的时刻(含日期,时间,时区) 注意NSLog(@“%@”,nowDate);⽆论你是哪个时区的时间,打印时总 ...

  9. [ python ] 项目二:主机批量管理程序

    开发要求: 1. 对主机进行批量管理    2. 可对单台或主机组批量执行命令    3. 可上传文件到对应的主机或组    4. 使用多线程实现  程序: 1. README # 作者:hkey # ...

  10. linux 设置开机启动项两种方式

    原文链接:http://blog.csdn.net/karchar/article/details/52489572 有时候我们需要Linux系统在开机的时候自动加载某些脚本或系统服务. 在解问题之前 ...