前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >YbtOJ 825「计算几何初探」三角查找

YbtOJ 825「计算几何初探」三角查找

作者头像
yzxoi
发布2022-09-19 13:38:58
2070
发布2022-09-19 13:38:58
举报
文章被收录于专栏:OI

YbtOJ 825「计算几何初探」三角查找

题目链接:YbtOJ #825

小 A 有一张二维平面,其中有 n 个点 (x_i,y_i)

他想要知道,是否存在三个点 (x_A,y_A),(x_B,y_B),(x_C,y_C),满足它们构成的三角形的面积 恰好 为 m

若存在,请给出任意一组符合条件的三个点。

3\le n\le2\times10^31\le m\le2\times10^{18}-10^9\le x_i,y_i\le 10^9,保证不存在三点共线。

Solution

暴力枚举每条连线作为三角形的底,然后只需要判断是否存在一个点到这条连线的距离恰好等于 \frac{2m}{l}

将这条线段旋成直角坐标系的纵轴,若能让所有点横坐标有序,就可以直接二分。于是问题就变成了如何维护点的顺序。

发现若将所有点两两之间的连线按斜率排遍序,按照斜率从小到大枚举,则任意两点的横坐标大小关系只会变化恰好一次。

初始所有点按原横坐标大小顺序排序,枚举连线的过程中每次交换两端点,再在连线两边分别二分查找即可。

Code

代码语言:javascript
复制
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define W while
#define I inline
#define RI register int
#define int long long
#define Cn const
#define CI Cn int&
using namespace std;
namespace Debug{
    Tp I void _debug(Cn char* f,Ty t){cerr<<f<<'='<<t<<endl;}
    Ts I void _debug(Cn char* f,Ty x,Ar... y){W(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);}
    Tp ostream& operator<<(ostream& os,Cn vector<Ty>& V){os<<"[";for(Cn auto& vv:V) os<<vv<<",";os<<"]";return os;}
    #define gdb(...) _debug(#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
namespace FastIO{
    #define FS 100000
    #define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    #define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    Tp I void read(Ty& x) {x=0;RI f=1;W(!isdigit(oc=tc())) f=oc^'-'?1:-1;W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));x*=f;}
    Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}using namespace FastIO;
Cn int N=2e3+10;
int n,m,cnt,id[N],r[N];
#define PA pair<int,int>
#define MP make_pair
#define fi first
#define se second
PA a[N];
struct Line{int u,v;PA d;}l[N*N];
I bool operator < (Cn Line& x,Cn Line& y){return x.d.fi*y.d.se-x.d.se*y.d.fi>0;}
I void G(RI tl,RI tr,Line u){
    auto S=[&](PA p)->int{return abs(p.fi*u.d.se-p.se*u.d.fi);};
    RI mid;W(tl<=tr) mid=tl+tr>>1,S(MP(a[id[mid]].fi-a[u.u].fi,a[id[mid]].se-a[u.u].se))==m&&(printf("Yes\n%d %d\n%d %d\n%d %d\n",a[u.u].fi,a[u.u].se,a[u.v].fi,a[u.v].se,a[id[mid]].fi,a[id[mid]].se),exit(0),0),S(MP(a[id[mid]].fi-a[u.u].fi,a[id[mid]].se-a[u.u].se))<m?tr=mid-1:tl=mid+1;
}
signed main(){
    freopen("triangle.in","r",stdin),freopen("triangle.out","w",stdout);
    RI i,j;for(read(n,m),m*=2,i=1;i<=n;i++) read(a[i].fi,a[i].se);for(sort(a+1,a+n+1),i=1;i<=n;i++) for(id[r[i]=i]=i,j=1;j<i;j++) l[++cnt]=(Line){i,j,MP(a[i].fi-a[j].fi,a[i].se-a[j].se)};
    for(sort(l+1,l+cnt+1),i=1;i<=cnt;i++) r[l[i].u]>r[l[i].v]&&(swap(l[i].u,l[i].v),0),G(1,r[l[i].u]-1,l[i]),swap(r[l[i].u],r[l[i].v]),swap(id[r[l[i].u]],id[r[l[i].v]]);
    return puts("No"),0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • YbtOJ 825「计算几何初探」三角查找
    • Solution
      • Code
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档