Description
已知两个x坐标不同的点可以确定一个二次项系数为1的二次函数。
现在给出n个点,问n^2个二次函数中有多少个图像不包含任何给出的关键点
n
≤
1
0
5
n\le10^5
n≤105
Solution
y=x2+bx+c,我们移项得到y-x2=bx+c,令y=y-x^2,那么就变成若干条直线求一个凸壳
当然直接做也可以,原理和上面是一样的
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fi first
#define se second
typedef std:: pair <int,int> pair;
typedef double db;
const db eps=1e-8;
const int N=200005;
std:: map <int,int> map;
struct pos {double x,y;} p[N],r[N],stk[N];
int top;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
pos get(pos a,pos b) {
double B=(b.y-a.y+a.x*a.x-b.x*b.x)/(b.x-a.x);
double C=(b.y-B*b.x-b.x*b.x);
return (pos) {B,C};
}
bool in(pos a,pos b) {
return (a.x*a.x+a.x*b.x+b.y-a.y>=-eps);
}
int main(void) {
int n; scanf("%d",&n);
rep(i,1,n) {
int x=read(),y=read();
p[i]=(pos) {(db)x,(db)y};
if (map.find(x)==map.end()) map[x]=y;
else {
if (y>map[x]) map[x]=y;
}
}
for (pair x:map) {
pos now=(pos) {(db)x.fi,(db)x.se};
pos tmp=get(stk[top-1],now);
while (top>1&&in(stk[top],get(stk[top-1],now))) top--;
stk[++top]=now;
}
printf("%d\n", top-1);
return 0;
}