题面
题解
易知 v ≠ 0 v\neq 0 v=0,那么直接考虑条件:
( x i u 2 + x i − u v − y i v ) b 2 ≤ ( x i a 2 + x i − a b − y i b ) v 2 x i u 2 + x i − u v − y i v v 2 ≤ x i a 2 + x i − a b − y i b b 2 \begin{aligned} \left(x_iu^2+x_i-uv-y_iv\right)b^2&\leq \left(x_ia^2+x_i-ab-y_ib\right)v^2\\ \frac{x_iu^2+x_i-uv-y_iv}{v^2}&\leq\frac{x_ia^2+x_i-ab-y_ib}{b^2} \end{aligned} (xiu2+xi−uv−yiv)b2v2xiu2+xi−uv−yiv≤(xia2+xi−ab−yib)v2≤b2xia2+xi−ab−yib
设 u ′ = u v u'=\dfrac{u}{v} u′=vu, v ′ = 1 v v'=\dfrac{1}{v} v′=v1, a ′ = a b a'=\dfrac{a}{b} a′=ba, b ′ = 1 b b'=\dfrac{1}{b} b′=b1,则原不等式变为:
x i u ′ 2 + x i v ′ 2 − u ′ − y i v ′ ≤ x i a ′ 2 + x i b ′ 2 − a ′ − y i b ′ x_iu'^2+x_iv'^2-u'-y_iv'\leq x_ia'^2+x_ib'^2-a'-y_ib' xiu′2+xiv′2−u′−yiv′≤xia′2+xib′2−a′−yib′
考虑配方:
x i u ′ 2 + x i v ′ 2 − u ′ − y i v ′ ≤ x i a ′ 2 + x i b ′ 2 − a ′ − y i b ′ u ′ 2 + v ′ 2 − 1 x i u ′ − y i x i v ′ ≤ a ′ 2 + b ′ 2 − 1 x i a ′ − y i x i b ′ ( u ′ 2 − 1 x i u ′ + 1 4 x i 2 ) + ( v ′ 2 − y i x i v ′ + y i 2 4 x i 2 ) ≤ ( a ′ 2 − 1 x i a ′ + 1 4 x i 2 ) + ( b ′ 2 − y i x i b ′ + y i 2 4 x i 2 ) ( u ′ − 1 2 x i ) 2 + ( v ′ − y i 2 x i ) 2 ≤ ( a ′ − 1 2 x i ) 2 + ( b ′ − y i 2 x i ) 2 \begin{aligned} x_iu'^2+x_iv'^2-u'-y_iv'&\leq x_ia'^2+x_ib'^2-a'-y_ib'\\ u'^2+v'^2-\frac{1}{x_i}u'-\frac{y_i}{x_i}v'&\leq a'^2+b'^2-\frac{1}{x_i}a'-\frac{y_i}{x_i}b'\\ \left(u'^2-\frac{1}{x_i}u'+\frac{1}{4x_i^2}\right)+\left(v'^2-\frac{y_i}{x_i}v'+\frac{y_i^2}{4x_i^2}\right) &\leq \left(a'^2-\frac{1}{x_i}a'+\frac{1}{4x_i^2}\right)+\left(b'^2-\frac{y_i}{x_i}b'+\frac{y_i^2}{4x_i^2}\right)\\ \left(u'-\frac{1}{2x_i}\right)^2+\left(v'-\frac{y_i}{2x_i}\right)^2 &\leq \left(a'-\frac{1}{2x_i}\right)^2+\left(b'-\frac{y_i}{2x_i}\right)^2 \end{aligned} xiu′2+xiv′2−u′−yiv′u′2+v′2−xi1u′−xiyiv′(u′2−xi1u′+4xi21)+(v′2−xiyiv′+4xi2yi2)(u′−2xi1)2+(v′−2xiyi)2≤xia′2+xib′2−a′−yib′≤a′2+b′2−xi1a′−xiyib′≤(a′2−xi1a′+4xi21)+(b′2−xiyib′+4xi2yi2)≤(a′−2xi1)2+(b′−2xiyi)2
其中左右分别可以看成是 ( u ′ , v ′ ) (u',v') (u′,v′) 和 ( a ′ , b ′ ) (a',b') (a′,b′) 到同一个点 ( 1 2 x i , y i 2 x i ) \left(\dfrac{1}{2x_i},\dfrac{y_i}{2x_i}\right) (2xi1,2xiyi) 的距离,其中 ( a ′ , b ′ ) (a',b') (a′,b′) 到 ( 1 2 x i , y i 2 x i ) \left(\dfrac{1}{2x_i},\dfrac{y_i}{2x_i}\right) (2xi1,2xiyi) 的距离是已知的,记为 R i R_i Ri。
那么这个不等式就是要求 ( u ′ , v ′ ) (u',v') (u′,v′) 这个点在以 ( 1 2 x i , y i 2 x i ) \left(\dfrac{1}{2x_i},\dfrac{y_i}{2x_i}\right) (2xi1,2xiyi) 为圆心、 R i R_i Ri 为半径的圆内或圆上,记这个圆为圆 O i O_i Oi( O i = ( 1 2 x i , y i 2 x i ) O_i=\left(\dfrac{1}{2x_i},\dfrac{y_i}{2x_i}\right) Oi=(2xi1,2xiyi)),那么 ⊙ O i \odot O_i ⊙Oi 过点 ( a ′ , b ′ ) (a',b') (a′,b′)。
那么如果 i i i 是答案的一种,当且仅当存在点 ( u ′ , v ′ ) (u',v') (u′,v′) 满足它被 ⊙ O i \odot O_i ⊙Oi 包含(“包含” 指含边界),且 ∀ j ≠ i \forall j\neq i ∀j=i 有 ( u ′ , v ′ ) (u',v') (u′,v′) 在 ⊙ O j \odot O_j ⊙Oj 外。也就是存在点 ( u ′ , v ′ ) (u',v') (u′,v′) 恰好只被圆 i i i 包含。
如何找到这些 i i i 呢?
我们考虑求出点集 { O , O 1 , O 2 , ⋯ , O n } \{O,O_1,O_2,\cdots,O_n\} {O,O1,O2,⋯,On} 的凸包,那么 i i i 是答案的一种当且仅当 O i O_i Oi 在凸包上。
感性证明:(以下证明都十分感性,真正的证明应该是用反演变换化曲为直来证)
分情况讨论:
-
若 O O O 不在凸包上。
那么考虑一个凸包内(不含边界)的点 A A A,显然一定可以找到两个在凸包上的相邻点 B , C B,C B,C 使得 A A A 在 △ O B C \triangle OBC △OBC 内,如图:
我们把这个三角形抽出来单独看,作出 ⊙ A , ⊙ B , ⊙ C \odot A,\odot B,\odot C ⊙A,⊙B,⊙C:
设 ⊙ A \odot A ⊙A 的过点 O O O 的直径交 ⊙ A \odot A ⊙A 于另一点 P A P_A PA,同理设出 P B P_B PB 和 P C P_C PC。
设 ⊙ B \odot B ⊙B 与 ⊙ C \odot C ⊙C 交于点 Q Q Q,那么容易得到 ∠ P B Q O = ∠ P C Q O = 90 ° \angle P_BQO=\angle P_CQO=90° ∠PBQO=∠PCQO=90°,那么 P B , Q , P C P_B,Q,P_C PB,Q,PC 三点共线。
容易看出 △ P B O P C \triangle P_BOP_C △PBOPC 是由 △ B O C \triangle BOC △BOC 位似变换得到,所以 A A A 在 △ B O C \triangle BOC △BOC 内运动可以看作是 P A P_A PA 在 △ P B O P C \triangle P_BOP_C △PBOPC 内运动:(颜色可能有点变化,请不要在意)
那么容易看出 ⊙ B \odot B ⊙B 与 ⊙ C \odot C ⊙C 的并集一定包含 ⊙ A \odot A ⊙A。
所以 ⊙ A \odot A ⊙A 所对应的 i i i 肯定不符合要求。
-
若 O O O 在凸包上。
与第一种情况是类似的,对于凸包内(不含边界)的某一个点 A A A,同样一定可以找到两个在凸包上的相邻点 B , C B,C B,C 使得 A A A 在 △ O B C \triangle OBC △OBC 内,如图:
接下来的证明过程和第一种情况类似。
感性地证毕。
整道题的大致流程就是这样。
还有一个小细节,你发现如果用 double
存点的话精度会爆炸。
然后又发现每一个点都是 ( x z , y z ) \left(\dfrac{x}{z},\dfrac{y}{z}\right) (zx,zy) 的形式,所以我们用三元组 ( x , y , z ) (x,y,z) (x,y,z) 存储一个点即可。
然后叉积判断等用 __int128
即可,具体详见代码。
代码如下:(细节很多)
#include<bits/stdc++.h>
#define N 100010
#define ll long long
#define lll __int128
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^'0');
ch=getchar();
}
return x*f;
}
struct Point
{
ll x,y,z;
int id;
}p[N],st[N];
inline int check(Point a,Point b,Point c)
{
lll x=(lll)(a.x*b.z-b.x*a.z)*(lll)(a.y*c.z-a.z*c.y);
lll y=(lll)(a.x*c.z-c.x*a.z)*(lll)(a.y*b.z-a.z*b.y);
if(x==y) return 0;
return x<y?-1:1;
}
inline bool inside(Point a,Point b,Point c)
{
if(a.x*b.z==b.x*a.z||b.x*c.z==c.x*b.z) return 1;
return !((a.x*b.z<b.x*a.z)^(b.x*c.z<c.x*b.z));
}
inline bool operator < (Point a,Point b)
{
int tmp=check(p[1],a,b);
if(!tmp)
{
if(p[1].x*a.z<=a.x*p[1].z&&p[1].x*b.z<=b.x*p[1].z) return a.x*b.z<b.x*a.z;
else return a.x*b.z>b.x*a.z;
}
return tmp>0;
}
inline bool operator == (Point a,Point b)
{
return a.x*b.z==b.x*a.z&&a.y*b.z==b.y*a.z;
}
int n;
int top;
bool vis[N];
bool ban[N];
void Graham()
{
for(int i=2;i<=n;i++)
if(p[i].y*p[1].z<p[1].y*p[i].z||
(p[i].y*p[1].z==p[1].y*p[i].z&&p[i].x*p[1].z<p[1].x*p[i].z))
swap(p[1],p[i]);
sort(p+2,p+n+1);
st[++top]=p[1];
for(register int i=2;i<=n;i++)
{
while(top>1)
{
int tmp=check(st[top-1],st[top],p[i]);
if(!tmp&&st[top]==p[i]) ban[st[top].id]=ban[p[i].id]=1;
if(tmp<0||(!tmp&&inside(st[top-1],st[top],p[i]))) top--;
else break;
}
st[++top]=p[i];
}
for(register int i=1;i<=top;i++) vis[st[i].id]=1;
}
int main()
{
n=read()+1;
p[1].x=read(),p[1].y=1,p[1].z=read();
for(register int i=2;i<=n;i++)
p[i].x=1,p[i].z=2ll*read(),p[i].y=read(),p[i].id=i-1;
Graham();
for(register int i=1;i<n;i++)
if(vis[i]&&!ban[i]) printf("%d ",i);
return 0;
}
/*
1 2 3
4 5
*/
/*
2 2 3
4 5
6 7
*/
/*
2 1 666666666
333333333 1
455943374 506861437
*/
/*
2 236701642 822463349
213494995 807598793
728662831 347575608
*/