设第$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. [官方教程] [ES4封装教程]2.使用 Easy Sysprep v4 封装 Windows XP

    (一)备份当前操作系统封装的第一步,其实是备份当前安装好的操作系统.避免我们在之后的步骤中出现问题,以至于还要重新安装操作系统,浪费时间精力.系统备份想必大家都会.对于WinXP而言,建议使用Ghos ...

  2. poj 3026 bfs+prim Borg Maze

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9718   Accepted: 3263 Description The B ...

  3. Linux rpm安装问题解决

    1.安装时提示:warning: *.rpm: Header V3 RSA/SHA256 Signature, keykey ID c105b9de: NOKEY 解决的方法就是在rpm 语句后面加上 ...

  4. 工作中常用shell之ssh登陆不用输入"yes"

    ip="192.168.5.166"ssh $ip -o StrictHostKeyChecking=no           //ssh登陆不用输入"yes" ...

  5. wget批量下载

    wget -i download.txt 这样就会把download.txt里面列出的每个URL都下载下来. wget -c http://the.url.of/incomplete/file 使用断 ...

  6. ListBox1控件

    前台: <div> <asp:ListBox ID="ListBox1" runat="server" AutoPostBack=" ...

  7. asp.net文本编辑器FCKeditor使用方法详解

    文本编辑器的使用: 1.FCKeditor的官方网站是:http://www.fckeditor.net/download  目前最新的FCKeditor.Net_2.6.9版本. 请在此页下载:ht ...

  8. 一些LUA函数(转载)

    转自http://hi.baidu.com/chevallet/item/9a3a6410c20d929198ce3363 一些LUA函数 1.assert (v [, message]) 功能:相当 ...

  9. Period(poj 1961)

    题目大意: 给你一个字符串,求这个字符串到第i个字符为止的循环节的次数. 比如aabaabaabaab,长度为12.到第二个a时,a出现2次,输出2.到第二个b时,aab出现了2次,输出2.到第三个b ...

  10. yum_rpm(利用dvd建立本地yum库)

    #wget "http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os" 建立起了index.html ...