luogu P5286 [HNOI2019]鱼
这题真的牛皮,还好考场没去刚(
这题口胡起来真的简单
首先枚举D点,然后对其他所有点按极角排序,同时记录到D的距离.然后按照极角序枚举A,那么鱼尾的两个点的极角范围就是A关于D对称的那个向量,然后左右各\(\frac{\pi}{2}\),因为A的极角增大,区间也会往后移,然后问题就是一个范围内同距离点对数,学过莫队的都会吧(逃
然后处理BC,一对合法的BC,首先要和AD垂直,然后BC中点要落在线段AD(不含端点)上,那么,BC中垂线必须唯一(中垂线的斜率和截距唯一),并且BC对应的中点的坐标范围要夹在A和D之间,然后预处理所有线段,按中垂线斜率,截距以及中点的x,y坐标之和三维度排序,每次有个AD,就能直接二分找到合法区间,然后直接算数量
注意BC,EF之间可以反过来,所以最后答案*4
代码仅供参考
// luogu-judger-enable-o2
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db long double
using namespace std;
const int N=1000+10;
const db eps=1e-13,pi=acos(-1);
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
struct point
{
db x,y;
point(){}
point(db nx,db ny){x=nx,y=ny;}
point operator - (const point &bb) const {return point(x-bb.x,y-bb.y);}
db operator * (const point &bb) const {return x*bb.x+y*bb.y;}
db operator ^(const point &bb) const {return x*bb.y-y*bb.x;}
}a[N],b[N],fk;
db sq(db x){return x*x;}
db dis(point aa,point bb){return sqrt(sq(aa.x-bb.x)+sq(aa.y-bb.y));}
db ang(point aa,point bb){return atan2(bb.y-aa.y,bb.x-aa.x);}
int n,m,bk[N];
LL ans,sb[N],tb,tc,na;
struct node
{
db dx,dy,b,x;
bool operator < (const node &bb) const
{
if(fabs(dy*bb.dx-dx*bb.dy)>eps) return dy*bb.dx<dx*bb.dy;
if(!dx&&fabs(b-bb.b)>eps) return b<bb.b;
else if(fabs(b*bb.dx-bb.b*dx)>eps) return b*bb.dx<bb.b*dx;
return x<bb.x;
}
}p2[N*N];
struct nn
{
db a,x,y;LL d;
bool operator < (const nn &bb) const {return a<bb.a;}
}vc[N<<1];
int main()
{
n=rd();
for(int i=1;i<=n;++i)
{
int x=rd(),y=rd();
a[i]=point(x,y);
}
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
{
db dx=-(a[i].y-a[j].y),dy=a[i].x-a[j].x,k=-(a[i].x-a[j].x+(fabs(a[i].x-a[j].x)<eps?eps:0))/(a[i].y-a[j].y+(fabs(a[i].y-a[j].y)<eps?eps:0));
if(dx<0) dx=-dx,dy=-dy;
if(fabs(dx)<eps) dy=1;
db mx=(a[i].x+a[j].x)/2,my=(a[i].y+a[j].y)/2,bb=dx*my-dy*mx;
p2[++m]=(node){dx,dy,dx?bb:mx,fabs(k+1)>eps?mx+my:mx};
}
sort(p2+1,p2+m+1);
p2[41]<p2[42];
for(int i=1;i<=n;++i)
{
memset(bk,0,sizeof(bk)),na=tb=tc=0;
for(int j=1;j<=n;++j)
if(i!=j)
{
LL sx=floor(a[i].x+0.5),sy=floor(a[i].y+0.5),tx=floor(a[j].x+0.5),ty=floor(a[j].y+0.5);
vc[++tc]=(nn){ang(a[i],a[j]),a[j].x,a[j].y,(sx-tx)*(sx-tx)+(sy-ty)*(sy-ty)};
sb[++tb]=(sx-tx)*(sx-tx)+(sy-ty)*(sy-ty);
}
sort(vc+1,vc+tc+1);
sort(sb+1,sb+tb+1),tb=unique(sb+1,sb+tb+1)-sb-1;
for(int j=1;j<=tc;++j) vc[j].d=lower_bound(sb+1,sb+tb+1,vc[j].d)-sb;
for(int j=1;j<=tc;++j) vc[j+tc]=vc[j],vc[j+tc].a+=pi+pi;
for(int j=1,l=1,r=0;j<=tc;++j)
{
while(r<tc+tc&&vc[r+1].a<vc[j].a+1.5*pi-eps) ++r,++bk[vc[r].d],na+=bk[vc[r].d]-1;
while(vc[l].a<vc[j].a+0.5*pi+eps) na-=bk[vc[l].d]-1,--bk[vc[l].d],++l;
db dx=a[i].x-vc[j].x,dy=a[i].y-vc[j].y,k=(a[i].y-vc[j].y+(fabs(a[i].y-vc[j].y)<eps?eps:0))/(a[i].x-vc[j].x+(fabs(a[i].x-vc[j].x)<eps?eps:0));
if(dx<0) dx=-dx,dy=-dy;
if(fabs(dx)<eps) dy=1;
db bb=a[i].y*dx-a[i].x*dy,ll=fabs(k+1)>eps?a[i].x+a[i].y:a[i].x,rr=fabs(k+1)>eps?vc[j].x+vc[j].y:vc[j].x;
if(ll>rr) swap(ll,rr);
int sl=upper_bound(p2+1,p2+m+1,(node){dx,dy,dx?bb:a[i].x,ll+eps})-p2,sr=lower_bound(p2+1,p2+m+1,(node){dx,dy,dx?bb:a[i].x,rr-eps})-p2-1;
ans+=na*(sr-sl+1);
}
}
printf("%lld\n",ans<<2);
//awsl
return 0;
}
luogu P5286 [HNOI2019]鱼的更多相关文章
- HNOI2019 鱼 fish
本来想写个改题记录的然后想了想改不完所以就分开写了= = https://www.luogu.org/problemnew/show/P5286 显然枚举A,D,然后鱼头和鱼身分开来考虑. 鱼身:先枚 ...
- [HNOI2019]鱼
Luogu5286 \(2019.4.14\),新生第一题,改了\(3\)个小时 题解-租酥雨,和出题人给的正解一模一样 枚举\(AD\),分别考虑鱼身\(BC\)和鱼尾\(EF\) 到\(E\),\ ...
- [HNOI2019]鱼(计算几何)
看到数据范围n<=1000,但感觉用O(n^2)不现实,所以考虑方向应该是O(n^2logn). 一种暴力做法:用vector存到1点相同的2点和到2点相同的1点,然后枚举A,枚举BC,再枚举D ...
- Luogu P5292 [HNOI2019]校园旅行
非常妙的一道思博题啊,不愧是myy出的题 首先我们考虑一个暴力DP,直接开一个数组\(f_{i,j}\)表示\(i\to j\)的路径能否构成回文串 考虑直接拿一个队列来转移,队列里存的都是\(f_{ ...
- luogu P5287 [HNOI2019]JOJO
传送门 神™这题暴力能A,这出题人都没造那种我考场就想到的数据,难怪我的垃圾做法有分 先考虑没有撤销操作怎么做,因为每次插入一段一样的字符,所以我们可以把\(x\)个字符\(c\)定义为\(cx\), ...
- luogu P5288 [HNOI2019]多边形
传送门 这是什么神仙操作... 首先要注意一些性质.首先每一个\((x,n)\)的边可以把当前多边形分成两半,这两半的操作是独立的.然后对于某一个没有\((x,n)\)的边的多边形,最优操作是唯一的. ...
- luogu P5293 [HNOI2019]白兔之舞
传送门 关于这题答案,因为在所有行,往后跳到任意一行的\(w_{i,j}\)都是一样的,所以可以算出跳\(x\)步的答案然后乘上\(\binom{l}{x}\),也就是枚举跳到了哪些行 如果记跳x步的 ...
- luogu P5294 [HNOI2019]序列
传送门 这个什么鬼证明直接看uoj的题解吧根本不会证明 首先方案一定是若干段等值的\(B\),然后对于一段,\(B\)的值应该是\(A\)的平均值.这个最优方案是可以线性构造的,也就是维护以区间平均值 ...
- 【洛谷5286】[HNOI2019] 鱼(计算几何)
点此看题面 大致题意: 给你\(n\)个点,让你求鱼形图的数量. 核心思路 首先,考虑到\(n\)这么小,我们可以枚举线段\(AD\),再去找符合条件的\(BC,EF\). 然后,不难发现\(BC\) ...
随机推荐
- day21-多并发编程基础(二)
今日要整理的内容有 1. 操作系统中线程理论 2.python中的GIL锁 3.线程在python中的使用 开始今日份整理 1. 操作系统中线程理论 1.1 线程引入背景 之前我们已经了解了操作系统中 ...
- Ubuntu 14.04 结束支持该如何应对?
Ubuntu 14.04 即将于 2019 年 4 月 30 日结束支持.这意味着在此日期之后 Ubuntu 14.04 用户将无法获得安全和维护更新. 你甚至不会获得已安装应用的更新,并且不手动修改 ...
- 树的平衡之AVL树——错过文末你会后悔,信我
学习数据结构应该是一个循序渐进的过程: 当我们学习数组时,我们要体会数组的优点:仅仅通过下标就可以访问我们要找的元素(便于查找). 此时,我们思考:假如我要在第一个元素前插入一个新元素?采用数组需要挪 ...
- Neutron flat network 学习
flat network 是不带 tag 的网络,要求宿主机的物理网卡直接与 linux bridge 连接,这意味着: 每个 flat network 都会独占一个物理网卡. 在 ML2 配置中 ...
- MySQL源码包编译安装
+++++++++++++++++++++++++++++++++++++++++++标题:MySQL数据库实力部署时间:2019年3月9日内容:MySQL源码包进行编译,然后部署MySQL单实例重点 ...
- Java 显示读取properties 乱码解决方案
项目开发时,在配置springmvc 校验错误提示信息时,配置到properties的中文,在前端取出时,显示为乱码,可以确定properties 配置文件已经被设为UTF-8编码,在springmv ...
- Android艺术——深看Activity的生命周期
探究Activity的生命周期 1.典型情况下的生命周期分析:onCreate 初始化工作,加载布局资源和数据:onStart ac正在启动但是无法交互,后台:onResume ac可见,显示在前台: ...
- 【并发编程】【JDK源码】J.U.C--组件FutureTask、ForkJoin、BlockingQueue
原文:慕课网实战·高并发探索(十三):并发容器J.U.C -- 组件FutureTask.ForkJoin.BlockingQueue FutureTask FutureTask是J.U.C中的类,是 ...
- 腾讯笔试---小Q的歌单
链接:https://www.nowcoder.com/questionTerminal/f3ab6fe72af34b71a2fd1d83304cbbb3 来源:牛客网 小Q有X首长度为A的不同的歌和 ...
- Elasticsearch6.5.2 X-pack破解及安装教程
先正常安装 elasticSearch, kibana. 1. 如果是6.5.2版本,可以直接下载jar文件:https://download.csdn.net/download/bigben0123 ...