- 巧妙的思维题.注意到这里只用两个点就可以确定一根抛物线,联想到两点确定一条直线,尝试转化.
- (y=x^2+bx+c) 就可以写成 (y-x^2=bx+c) ,可以发现,将点 ((x_i,y_i)) 变为 ((x_i,y_i-x_i^2)) 后,就变成了对每对点连一条直线,答案就是上凸壳的边数.
- 注意在统计答案时,不能计算两点 (x) 相同的直线.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
int x=0;
bool pos=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
pos=0;
for(;isdigit(ch);ch=getchar())
x=x*10+ch-'0';
return pos?x:-x;
}
const int MAXN=1e5+10;
int n;
struct v2
{
double x,y;
v2(double x=0,double y=0):x(x),y(y) {}
friend double operator * (const v2 &a,const v2 &b)
{
return a.x*b.y-a.y*b.x;
}
friend v2 operator + (const v2 &a,const v2 &b)
{
return v2(a.x+b.x,a.y+b.y);
}
friend v2 operator - (const v2 &a,const v2 &b)
{
return v2(a.x-b.x,a.y-b.y);
}
bool operator < (const v2 &rhs) const
{
return x==rhs.x?y<rhs.y:x<rhs.x;
}
double modulus()
{
return sqrt(x*x+y*y);
}
double angle()
{
return atan2(y,x);
}
}p[MAXN];
v2 stk[MAXN];
int tp=0;
v2 origin;
bool cmp(const v2 &a,const v2 &b)
{
double a1=(a-origin).angle();
double a2=(b-origin).angle();
return a1==a2?a.x<b.x:a1<a2;
}
void ConvexHull()
{
for(int i=2;i<=n;++i)
if(p[i]<p[1])
swap(p[i],p[1]);
origin=p[1];
sort(p+2,p+1+n,cmp);
for(int i=1;i<=n;++i)
{
while(tp>=2 && (stk[tp]-stk[tp-1])*(p[i]-stk[tp])<=0)
--tp;
stk[++tp]=p[i];
}
stk[++tp]=p[1];
}
#define eps 1e-12
int main()
{
n=read();
for(int i=1;i<=n;++i)
{
int x=read(),y=read();
p[i]=v2((double)x,(double)(y-1LL*x*x));
}
ConvexHull();
if(tp==3)
{
if(fabs(stk[1].x-stk[2].x)<eps)
cout<<0<<endl;
else
cout<<1<<endl;
return 0;
}
int ans=0;
for(int i=1;i<tp;++i)
{
int j=(i==1)?3:i-1;
if(fabs(stk[i+1].x-stk[i].x)<eps)
continue;
double y=stk[i].y+(stk[j].x-stk[i].x)/(stk[i+1].x-stk[i].x)*(stk[i+1].y-stk[i].y);
if(y-stk[j].y>eps)
++ans;
}
cout<<ans<<endl;
return 0;
}