[SCOI2016]妖怪

来写一个三分套三分的写法。

我们发现对于一个 ((a,b)),式子即为 (x+y+frac{b}{a}x+frac{a}{b}y),所以之和 (frac{b}{a}) 有关,我们三分 (frac{b}{a}),关键是如何快速找到最大值。我们发现这是一条直线,答案是与y轴和x轴交点到原点的距离和,那么显然答案是在上凸包上,且在上凸包上具有三分性,再来个三分即可。

#include<bits/stdc++.h>
using namespace std;
const double inf=1e18;
const double eps=1e-14;
struct node{
 double x,y;
 friend bool operator < (node a,node b){
  if(a.x==b.x)return a.y<b.y;
  return a.x<b.x;
 }
}p[1000005],stk[1000005];
int n,top;
double slope(node a,node b) {
 if(a.x==b.x)return b.y>=a.y?inf:-inf;
 return (b.y-a.y)/(b.x-a.x);
}
double get(double K,int id){
 return stk[id].x*(K+1)+stk[id].y*(1/K+1);
}
double check(double K){
 int l=1,r=top;
 double ret=max(get(K,1),get(K,top));
 while (l<r-1){
  int m1=l+(r-l+1)/3;
  int m2=r-(r-l+1)/3;
  if(get(K,m1)>get(K,m2))r=m2;
  else l=m1;
 }
 return max(ret,max(get(K,l),get(K,r)));
}
int main(){
 scanf("%d",&n);
 for(int i=1;i<=n;i++){
  scanf("%lf%lf",&p[i].x,&p[i].y);
 }
 sort(p+1,p+1+n);
 for(int i=1;i<=n;i++){
  while(top>1&&slope(stk[top-1],stk[top])<=slope(stk[top],p[i]))top--;
  stk[++top]=p[i];
 }
 double l=0,r=1e9;
 while(r-l>eps){
  double m1=l+(r-l)/3;
  double m2=r-(r-l)/3;
  if(check(m1)<check(m2))r=m2;
  else l=m1;
 }
 printf("%.4lf
",min(check(l),check(r)));
 return 0;
}
原文地址:https://www.cnblogs.com/zcr-blog/p/14332818.html