设第$i$条直线的解析式为$a_ix+b_iy+c_i=0$,$d_i=a_i^2+b_i^2$,则要求一个点$(x,y)$,使得$sumleft(frac{left|a_ix+b_iy+c_i ight|}{sqrt{d_i}} ight)^2$最小。
假设$x$固定,则
[egin{eqnarray*}ans&=&sumleft(frac{left|a_ix+b_iy+c_i ight|}{sqrt{d_i}} ight)^2\&=&sumfrac{left(a_ix+b_iy+c_i ight)^2}{d_i}\&=&sumfrac{left(b_iy+a_ix+c_i ight)^2}{d_i}\&=&sumleft(frac{b_i^2y^2}{d_i}+frac{2b_ileft(a_ix+c_i ight)y}{d_i}+frac{left(a_ix+c_i ight)^2}{d_i} ight)\&=&sumfrac{b_i^2y^2}{d_i}+sumfrac{2b_ileft(a_ix+c_i ight)y}{d_i}+sumfrac{left(a_ix+c_i ight)^2}{d_i}\&=&y^2sumfrac{b_i^2}{d_i}+2ysumfrac{b_ileft(a_ix+c_i ight)}{d_i}+sumfrac{left(a_ix+c_i ight)^2}{d_i}\&=&y^2sumfrac{b_i^2}{d_i}+2yleft(sumfrac{a_ib_ix}{d_i}+sumfrac{b_ic_i}{d_i} ight)+sumfrac{left(a_ix+c_i ight)^2}{d_i}\&=&y^2sumfrac{b_i^2}{d_i}+2yleft(xsumfrac{a_ib_i}{d_i}+sumfrac{b_ic_i}{d_i} ight)+sumfrac{left(a_ix+c_i ight)^2}{d_i}end{eqnarray*}]
当$y$取对称轴时取得最小值,此时
[egin{eqnarray*}y&=&-frac{2left(xsumfrac{a_ib_i}{d_i}+sumfrac{b_ic_i}{d_i} ight)}{2sumfrac{b_i^2}{d_i}}\&=&-frac{xsumfrac{a_ib_i}{d_i}+sumfrac{b_ic_i}{d_i}}{sumfrac{b_i^2}{d_i}}\&=&-frac{sumfrac{a_ib_i}{d_i}}{sumfrac{b_i^2}{d_i}}x-frac{sumfrac{b_ic_i}{d_i}}{sumfrac{b_i^2}{d_i}}\&=&Ax+B\A&=&-frac{sumfrac{a_ib_i}{d_i}}{sumfrac{b_i^2}{d_i}}\B&=&-frac{sumfrac{b_ic_i}{d_i}}{sumfrac{b_i^2}{d_i}}end{eqnarray*}]
将$y$用$Ax+B$表示,则
[egin{eqnarray*}ans&=&sumfrac{left(a_ix+b_iy+c_i ight)^2}{d_i}\&=&sumfrac{left(a_ix+b_ileft(Ax+B ight)+c_i ight)^2}{d_i}\&=&sumfrac{left(a_ix+Ab_ix+Bb_i+c_i ight)^2}{d_i}\&=&sumfrac{left(left(a_i+Ab_i ight)x+Bb_i+c_i ight)^2}{d_i}\&=&sumfrac{left(a_i+Ab_i ight)^2x^2+2left(a_i+Ab_i ight)left(Bb_i+c_i ight)x+left(Bb_i+c_i ight)^2}{d_i}\&=&sumleft( frac{left(a_i+Ab_i ight)^2x^2}{d_i}+frac{2left(a_i+Ab_i ight)left(Bb_i+c_i ight)x}{d_i}+frac{left(Bb_i+c_i ight)^2}{d_i} ight)\&=&x^2sumfrac{left(a_i+Ab_i ight)^2}{d_i}+2xsumfrac{left(a_i+Ab_i ight)left(Bb_i+c_i ight)}{d_i}+sumfrac{left(Bb_i+c_i ight)^2}{d_i}\&=&Ux^2+Vx+W\U&=&sumfrac{left(a_i+Ab_i ight)^2}{d_i}\&=&sumfrac{a_i^2+2Aa_ib_i+A^2b_i^2}{d_i}\&=&sumfrac{a_i^2}{d_i}+2Asumfrac{a_ib_i}{d_i}+A^2sumfrac{b_i^2}{d_i}\V&=&2sumfrac{left(a_i+Ab_i ight)left(Bb_i+c_i ight)}{d_i}\&=&2sumfrac{Ba_ib_i+a_ic_i+ABb_i^2+Ab_ic_i}{d_i}\&=&2left(Bsumfrac{a_ib_i}{d_i}+sumfrac{a_ic_i}{d_i}+ABsumfrac{b_i^2}{d_i}+Asumfrac{b_ic_i}{d_i} ight)\W&=&sumfrac{left(Bb_i+c_i ight)^2}{d_i}\&=&sumfrac{B^2b_i^2+2Bb_ic_i+c_i^2}{d_i}\&=&B^2sumfrac{b_i^2}{d_i}+2Bsumfrac{b_ic_i}{d_i}+sumfrac{c_i^2}{d_i}end{eqnarray*}]
若$U=0$,则最小值为$W$,否则当$x$取对称轴时取得最小值,此时$x=-frac{V}{2U}$,假设我们已经知道了$sumfrac{a_i^2}{d_i},sumfrac{b_i^2}{d_i},sumfrac{c_i^2}{d_i},sumfrac{a_ib_i}{d_i},sumfrac{a_ic_i}{d_i},sumfrac{b_ic_i}{d_i}$,则答案可以$O(1)$求出。
对于修改操作,只要$O(1)$修改这六个值即可。
至此,本题在$O(N)$复杂度内被解决。
#include<cstdio> #include<cmath> #define N 120010 int n,q,op,i,m; double X1,X2,Y1,Y2,a,b,c,d,aa[N],bb[N],cc[N],ab[N],ac[N],bc[N],saa,sbb,scc,sab,sac,sbc,eps=1e-8,ans; inline bool zero(double x){return std::fabs(x)<eps;} inline double solve(double a,double b,double c){ if(zero(a))return c; double x=-b/(2.0*a); return a*x*x+b*x+c; } int main(){ scanf("%d",&q); while(q--){ scanf("%d",&op); if(op==0){ scanf("%lf%lf%lf%lf",&X1,&Y1,&X2,&Y2); if(zero(X1-X2))a=1,b=0,c=-X1;else a=(Y2-Y1)/(X2-X1),b=-1,c=Y1-a*X1; d=a*a+b*b; aa[++n]=a*a/d,bb[n]=b*b/d,cc[n]=c*c/d,ab[n]=a*b/d,ac[n]=a*c/d,bc[n]=b*c/d; saa+=aa[n],sbb+=bb[n],scc+=cc[n],sab+=ab[n],sac+=ac[n],sbc+=bc[n]; m++; } if(op==1){ scanf("%d",&i); saa-=aa[i],sbb-=bb[i],scc-=cc[i],sab-=ab[i],sac-=ac[i],sbc-=bc[i]; m--; } if(op==2){ if(!m){puts("0.00");continue;} if(zero(sbb))a=b=0;else a=-sab/sbb,b=-sbc/sbb; ans=solve(saa+2.0*a*sab+a*a*sbb,2.0*(b*sab+sac+a*b*sbb+a*sbc),b*b*sbb+2.0*b*sbc+scc); if(zero(ans))ans=0; printf("%.2f ",ans); } } return 0; }