设第$i$条直线的解析式为$a_ix+b_iy+c_i=0$,$d_i=a_i^2+b_i^2$,则要求一个点$(x,y)$,使得$\sum\left(\frac{\left|a_ix+b_iy+c_i\right|}{\sqrt{d_i}}\right)^2$最小。

假设$x$固定,则

\[\begin{eqnarray*}ans&=&\sum\left(\frac{\left|a_ix+b_iy+c_i\right|}{\sqrt{d_i}}\right)^2\\&=&\sum\frac{\left(a_ix+b_iy+c_i\right)^2}{d_i}\\&=&\sum\frac{\left(b_iy+a_ix+c_i\right)^2}{d_i}\\&=&\sum\left(\frac{b_i^2y^2}{d_i}+\frac{2b_i\left(a_ix+c_i\right)y}{d_i}+\frac{\left(a_ix+c_i\right)^2}{d_i}\right)\\&=&\sum\frac{b_i^2y^2}{d_i}+\sum\frac{2b_i\left(a_ix+c_i\right)y}{d_i}+\sum\frac{\left(a_ix+c_i\right)^2}{d_i}\\&=&y^2\sum\frac{b_i^2}{d_i}+2y\sum\frac{b_i\left(a_ix+c_i\right)}{d_i}+\sum\frac{\left(a_ix+c_i\right)^2}{d_i}\\&=&y^2\sum\frac{b_i^2}{d_i}+2y\left(\sum\frac{a_ib_ix}{d_i}+\sum\frac{b_ic_i}{d_i}\right)+\sum\frac{\left(a_ix+c_i\right)^2}{d_i}\\&=&y^2\sum\frac{b_i^2}{d_i}+2y\left(x\sum\frac{a_ib_i}{d_i}+\sum\frac{b_ic_i}{d_i}\right)+\sum\frac{\left(a_ix+c_i\right)^2}{d_i}\end{eqnarray*}\]

当$y$取对称轴时取得最小值,此时

\[\begin{eqnarray*}y&=&-\frac{2\left(x\sum\frac{a_ib_i}{d_i}+\sum\frac{b_ic_i}{d_i}\right)}{2\sum\frac{b_i^2}{d_i}}\\&=&-\frac{x\sum\frac{a_ib_i}{d_i}+\sum\frac{b_ic_i}{d_i}}{\sum\frac{b_i^2}{d_i}}\\&=&-\frac{\sum\frac{a_ib_i}{d_i}}{\sum\frac{b_i^2}{d_i}}x-\frac{\sum\frac{b_ic_i}{d_i}}{\sum\frac{b_i^2}{d_i}}\\&=&Ax+B\\A&=&-\frac{\sum\frac{a_ib_i}{d_i}}{\sum\frac{b_i^2}{d_i}}\\B&=&-\frac{\sum\frac{b_ic_i}{d_i}}{\sum\frac{b_i^2}{d_i}}\end{eqnarray*}\]

将$y$用$Ax+B$表示,则

\[\begin{eqnarray*}ans&=&\sum\frac{\left(a_ix+b_iy+c_i\right)^2}{d_i}\\&=&\sum\frac{\left(a_ix+b_i\left(Ax+B\right)+c_i\right)^2}{d_i}\\&=&\sum\frac{\left(a_ix+Ab_ix+Bb_i+c_i\right)^2}{d_i}\\&=&\sum\frac{\left(\left(a_i+Ab_i\right)x+Bb_i+c_i\right)^2}{d_i}\\&=&\sum\frac{\left(a_i+Ab_i\right)^2x^2+2\left(a_i+Ab_i\right)\left(Bb_i+c_i\right)x+\left(Bb_i+c_i\right)^2}{d_i}\\&=&\sum\left( \frac{\left(a_i+Ab_i\right)^2x^2}{d_i}+\frac{2\left(a_i+Ab_i\right)\left(Bb_i+c_i\right)x}{d_i}+\frac{\left(Bb_i+c_i\right)^2}{d_i}\right)\\&=&x^2\sum\frac{\left(a_i+Ab_i\right)^2}{d_i}+2x\sum\frac{\left(a_i+Ab_i\right)\left(Bb_i+c_i\right)}{d_i}+\sum\frac{\left(Bb_i+c_i\right)^2}{d_i}\\&=&Ux^2+Vx+W\\U&=&\sum\frac{\left(a_i+Ab_i\right)^2}{d_i}\\&=&\sum\frac{a_i^2+2Aa_ib_i+A^2b_i^2}{d_i}\\&=&\sum\frac{a_i^2}{d_i}+2A\sum\frac{a_ib_i}{d_i}+A^2\sum\frac{b_i^2}{d_i}\\V&=&2\sum\frac{\left(a_i+Ab_i\right)\left(Bb_i+c_i\right)}{d_i}\\&=&2\sum\frac{Ba_ib_i+a_ic_i+ABb_i^2+Ab_ic_i}{d_i}\\&=&2\left(B\sum\frac{a_ib_i}{d_i}+\sum\frac{a_ic_i}{d_i}+AB\sum\frac{b_i^2}{d_i}+A\sum\frac{b_ic_i}{d_i}\right)\\W&=&\sum\frac{\left(Bb_i+c_i\right)^2}{d_i}\\&=&\sum\frac{B^2b_i^2+2Bb_ic_i+c_i^2}{d_i}\\&=&B^2\sum\frac{b_i^2}{d_i}+2B\sum\frac{b_ic_i}{d_i}+\sum\frac{c_i^2}{d_i}\end{eqnarray*}\]

若$U=0$,则最小值为$W$,否则当$x$取对称轴时取得最小值,此时$x=-\frac{V}{2U}$,假设我们已经知道了$\sum\frac{a_i^2}{d_i},\sum\frac{b_i^2}{d_i},\sum\frac{c_i^2}{d_i},\sum\frac{a_ib_i}{d_i},\sum\frac{a_ic_i}{d_i},\sum\frac{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\n",ans);
}
}
return 0;
}

  

BZOJ3775 : 点和直线的更多相关文章

  1. BZOJ3775: 点和直线(计算几何+拉格朗日乘数法)

    题面 传送门 题解 劲啊-- 没有和\(Claris\)一样推,用了类似于\(Shinbokuow\)推已知点求最短直线的方法,结果\(WA\)了好几个小时,拿\(Claris\)代码拍了几个小时都没 ...

  2. MFC中如何画带实心箭头的直线

    工作中遇到话流程图的项目,需要画带箭头的直线,经过摸索,解决:思路如下: (1) 两个点(p1,p2)确定一个直线,以直线的一个端点(假设p2)为原点,设定一个角度 (2)以P2为原点得到向量P2P1 ...

  3. 水平可见直线 bzoj 1007

    水平可见直线 (1s 128M) lines [问题描述] 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆 ...

  4. SVG:linearGradient渐变在直线上失效的问题解决方案

    SVG开发里有个较为少见的问题. 对x1=x2或者y1=y2的直线(line以及path),比如: <path d="M200,10 200,100" stroke=&quo ...

  5. 封装 用canvas绘制直线的函数--面向对象

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. [bzoj1007][HNOI2008][水平可见直线] (斜率不等式)

    Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为 可见的,否则Li为被覆盖的. 例如,对于直线: L1:y ...

  7. [LeetCode] Line Reflection 直线对称

    Given n points on a 2D plane, find if there is such a line parallel to y-axis that reflect the given ...

  8. 点(x3,y3)到经过点(x1,y1)和点(x2,y2)的直线的最短距离

    /// <summary> /// 点(x3,y3)到经过点(x1,y1)和点(x2,y2)的直线的最短距离 /// </summary> /// <param name ...

  9. CoreGraphics-基本图形绘制-直线、三角形、矩形、椭圆形、弧形

    框架:CoreGraphics 步骤: 1."获取"图形上下文     let cxtRef = UIGraphicsGetCurrentContext()! 2.添加路径 3.渲 ...

随机推荐

  1. MFC加载皮肤 转自:http://www.cctry.com/thread-4032-1-1.html

    VC皮肤库SkinSharp 1.0.6.6的使用: SkinSharp又称Skin#,是Windows环境下一款强大的换肤组件.SkinSharp作为换肤控件,只需要在您的程序中添加一行代码,就能让 ...

  2. KMP算法心得

    今天又看了一遍KMP,感觉真的懂了...就来这儿发一下心得吧. KMP算法其实就是暴力的改进版.让我们看看暴力的匹配. Original string: ababababcbbababababc Pa ...

  3. 细微之处:比较两种CSS清除浮动的兼容

    http://www.cnblogs.com/bienfantaisie/archive/2011/05/27/2059597.html 清除浮动是连续浮动元素之后的必备工作,在工作中我做到需要清除浮 ...

  4. python代码中使用settings

    在具体的Django应用中,通过引入 django.conf.settings 使用配置,例: from django.conf import settings settings.configure( ...

  5. spring事物传播属性

    PROPAGATION_REQUIRED Support a current transaction; create a new one if none exists.  支持一个当前事务;如果不存在 ...

  6. Eclipse 一直提示 loading descriptor for 的解决方法(转)

    启动eclipse之后,进行相关操作时,弹出界面,提示:loading descriptor for xxx 解决方法: 在Eclipse左侧的Project Explorer 最右上角有一个小钮,鼠 ...

  7. bat批量去除文件首行和合并到文件

    bat批量去除文件首行 set n=1 :starline for %%j in (*.txt) do ( :3 if exist D:\work\test\new_%n%.txt (set /a n ...

  8. [转]C程序内存区域分配(5个段作用)

    [转]C程序内存区域分配(5个段作用) 2012-08-10 14:45:32|  分类: C++基础|字号 订阅     参考:http://www.360doc.com/content/11/03 ...

  9. 菜单栏展开和收起效果(纯js)

    2014年6月25日 15:36:29 需要关注的是: 1.用cookie保存用户当前点击的菜单项,不打扰后端代码 2.通过数学计算得到要显示和隐藏的div 3.点击事件是动态绑定到a标签上的,因此当 ...

  10. HDU5072 容斥原理

    G - Coprime Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit ...