题意

https://loj.ac/problem/2201

思路

说白了就是一条路径上有 \(n\) 个二维坐标,求一条直线使得所有点到此直线的距离和最小。

设这条直线为 \(y=kx+b\) ,距离和为 \(\delta\)。
\[ \delta=\sum{(kx_i-y_i+b)^2\over k^2+1} \]

\[ \delta={k^2\sum x_i^2+\sum y_i^2+nb^2-2k\sum x_iy_i+2kb\sum x_i-2b\sum y_i\over k^2+1} \]
由于 \(k,b\) 的取值互不影响,我们先假设 \(k\) 是一个常量,变形如下
\[ \delta={nb^2+(2k\sum x_i-2\sum y_i)b+k^2\sum x_i^2-2k\sum x_iy_i+\sum y_i^2\over k^2+1} \]
发现就是一个关于 \(b\) 的二次方程,开口朝上,顶点处取最小值,即
\[ b=-{2k\sum x_i-2\sum y_i\over 2n}={\sum y_i\over n}-k{\sum x_i\over n} \]
设 \(\displaystyle\bar x={\sum x_i\over n},\displaystyle\bar y={\sum y_i\over n}\)

得出 \(b=\bar y-k\bar x\)

代入并化简成关于 \(k\) 的式子得到
\[ \delta={{(\sum x_i^2-2\bar x\sum x_i+n\bar x^2)k^2+(-2\sum x_iy_i+2\bar y \sum x_i+2\bar x\sum y_i-2n\bar x\bar y)k+(\sum y_i^2-2\bar y\sum y_i+n\bar y^2)}\over k^2+1} \]

\[ \begin{array}{} A&=\sum x_i^2-2\bar x\sum x_i+n\bar x^2\\ &=\sum x_i^2-{(\sum x_i)^2\over n}\\ B&=-2\sum x_iy_i+2\bar y \sum x_i+2\bar x\sum y_i-2n\bar x\bar y\\ &=-2\sum x_iy_i+2{\sum x_i\sum y_i\over n}\\ C&=\sum y_i^2-2\bar y\sum y_i+n\bar y^2\\ &=\sum y_i^2-{(\sum y_i)^2\over n} \end{array} \]
那么
\[ \delta={Ak^2+Bk+C\over k^2+1} \]
把 \(k\) 当作主元化简得
\[ (A-\delta)k^2+Bk+C-\delta=0 \]
这个二次方程的 \(\Delta\) 为 \(B^2-4(A-\delta)(C-\delta)\)
\[ B^2-4(A-\delta)(C-\delta)\ge 0\\ -4\delta ^2+4(A+C)\delta-4AC+B^2 \ge 0 \]
解得 \(\displaystyle\delta={A+C\pm \sqrt{A^2-2AC+B^2+C^2}\over 2}\)

根号前取负号即可达到最小值.

所以维护六元组 \((\sum x_i,\sum y_i,\sum x_i^2,\sum y_i^2,\sum x_iy_i,\sum1)\) 即可求出 \(A,B,C\) ,求出 \(\delta\) 的最小值。

树的情况只用维护到根路径上的信息即可。

基环树的情况类似,断开一条环边,再枚举可行路径(至多两条)即可。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=(int)1e5+5;
template<const int maxn,const int maxm,typename T>struct Linked_list
{int head[maxn],nxt[maxm],tot;T to[maxm];Linked_list(){clear();}T &operator [](const int x){return to[x];}void clear(){memset(head,-1,sizeof(head)),tot=0;}void add(int u,T v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
struct DisjointSet
{int fa[N];void init(int n){FOR(i,1,n)fa[i]=i;}int get_fa(int x){return x==fa[x]?x:fa[x]=get_fa(fa[x]);}void merge(int x,int y){x=get_fa(x),y=get_fa(y);if(x==y)return;fa[x]=y;}
};
struct hexa
{int a,b,c,d,e,f;hexa(int _a=0,int _b=0,int _c=0,int _d=0,int _e=0,int _f=0){a=_a,b=_b,c=_c,d=_d,e=_e,f=_f;}hexa operator +(const hexa &_)const{return hexa(a+_.a,b+_.b,c+_.c,d+_.d,e+_.e,f+_.f);}hexa operator -(const hexa &_)const{return hexa(a-_.a,b-_.b,c-_.c,d-_.d,e-_.e,f-_.f);}hexa add(int x,int y){return hexa(a+x,b+y,c+x*x,d+y*y,e+x*y,f+1);}double solve(){double A=c-1.0*a*a/f,B=-2*e+2.0*a*b/f,C=d-1.0*b*b/f;return (A+C-sqrt(A*A-2*A*C+B*B+C*C))/2;}
};
hexa sum[N];
DisjointSet D;
Linked_list<N,N<<1,int>G;
int dep[N],fa[N],sz[N],son[N],top[N];
int X[N],Y[N];
int n,m,q;
int U,V;void dfs(int u,int f,int d)
{dep[u]=d,fa[u]=f,sz[u]=1,son[u]=0;sum[u]=sum[f].add(X[u],Y[u]);EOR(i,G,u){int v=G[i];if(v==f)continue;dfs(v,u,d+1);sz[u]+=sz[v];if(sz[v]>sz[son[u]])son[u]=v;}
}
void hld(int u,int f,int tp)
{top[u]=tp;if(son[u])hld(son[u],u,tp);EOR(i,G,u){int v=G[i];if(v==f||v==son[u])continue;hld(v,u,v);}
}
int get_lca(int x,int y)
{while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])std::swap(x,y);x=fa[top[x]];}return dep[x]<dep[y]?x:y;
}
int get_dis(int x,int y)
{return dep[x]+dep[y]-2*dep[get_lca(x,y)];
}
hexa get_val(int x,int y)
{int lca=get_lca(x,y);return (sum[x]-sum[lca]+sum[y]-sum[lca]).add(X[lca],Y[lca]);
}
bool intersect(int a,int b,int c,int d)
{int lca1=get_lca(a,b),lca2=get_lca(c,d);return  get_dis(a,lca2)+get_dis(lca2,b)==get_dis(a,b)||get_dis(c,lca1)+get_dis(lca1,d)==get_dis(c,d);
}int main()
{scanf("%d%d",&n,&m);FOR(i,1,n)scanf("%d%d",&X[i],&Y[i]);D.init(n);FOR(i,1,m){int u,v;scanf("%d%d",&u,&v);if(D.get_fa(u)==D.get_fa(v))U=u,V=v;else{G.add(u,v),G.add(v,u);D.merge(u,v);}}dfs(1,0,1);hld(1,0,1);scanf("%d",&q);while(q--){int x,y;scanf("%d%d",&x,&y);if(n==m-1)printf("%.5lf\n",get_val(x,y).solve());else{double res=get_val(x,y).solve();if(!intersect(x,U,y,V))chk_min(res,(get_val(x,U)+get_val(y,V)).solve());if(!intersect(x,V,y,U))chk_min(res,(get_val(x,V)+get_val(y,U)).solve());printf("%.5lf\n",res);}}return 0;
}

转载于:https://www.cnblogs.com/Paulliant/p/10777570.html

ZJOI 2014 星系调查(推导)相关推荐

  1. bzoj 3528: [Zjoi2014]星系调查

    Description 银河历59451年,在银河系有许许多多已被人类殖民的星系.如果想要在行 星系间往来,大家一般使用连接两个行星系的跳跃星门.  一个跳跃星门可以把 物质在它所连接的两个行星系中互 ...

  2. OpenStack 2014 用户调查解析——中国部署规模仅次于美国

    作者:郑晨,OpenStack中国社区,转载请注明出处 编者按:OpenStack已经愈见成熟,本届峰会的主要议程已经接近尾声,"超级用户"们已经在峰会当中就OpenStack的企 ...

  3. [ZJOI2014] 星系调查(树上差分 + 数学推式子)

    problem luogu-P3340 题面写得那么长,其实说白了就是求一条直线,使得若干个点到这条直线的距离平方的和最小,求这个最小值. solution 我超爱数学,数学就是我的命,我一天不学数学 ...

  4. [置顶] 2014年八大最热门IT技能

    根据Computerworld网站组织的年度预测调查,众多IT专业人士在2014年所面临的整体就业形势与今年基本持平--今年有33%的企业有计划增加IT部门的员工数量,而未来一年则有32%的企业有此打 ...

  5. 2013-2014嵌入式开发从业人员调查报告

    调查背景 在嵌入式.移动互联网.物联网等热门技术日益普及的今天,以实现智能化为核心目标的典型技术,已经成为了整个信息产业毋庸置疑的主旋律.特别是近1年,以智能家居.智能医疗.可穿戴设备等为首的大量智能 ...

  6. 2014年八大最热门IT技能

    根据Computerworld网站组织的年度预测调查,众多IT专业人士在2014年所面临的整体就业形势与今年基本持平--今年有33%的企业有计划增加IT部门的员工数量,而未来一年则有32%的企业有此打 ...

  7. linux 64 内存管理,[内存管理]linux X86_64处理器的内存布局图

    Windbg学习使用 WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件. 1. WinDbg介绍:  ...

  8. 城市交通出行效率对比分析与思考

    来源:规划与交通 出行效率是指居民以最少的出行投入(包含最少的货币成本和时间成本.最舒适和最安全的出行体验等),利用某种交通方式完成某种出行目的的活动.出行效率强调的是"全过程"出 ...

  9. Trends, Limitations and Open Challenges inAutomatic Readability Assessment Research翻译

    摘要 可读性评估是对给定文本的阅读难度进行评估的一项任务.虽然对可读性评估的计算方法的研究已经有20年的历史了,但是对这一研究的综合研究还没有太多的工作.本文是对当前可读性评估计算模型发展的简要综述. ...

最新文章

  1. PHP_crontab 漏洞,shopex 4.8.5.45144 \core\include_v5\crontab.php 远程shell写入漏洞
  2. ubuntu12.04 升级 automake
  3. RTMP直播应用与延时分析
  4. [转载]大型网站架构演变和知识体系
  5. 精简ICO图标可减小EXE程序文件大小
  6. 80后的我,记忆里和吃有关的那些事
  7. javacc LOOKAHEAD关键字
  8. oracle.jdbc.driver.OracleDriver is deprecated
  9. 如何发现适合自己深度投入的领域?
  10. uniapp中后端返回的数字字符串如何在页面快速计算
  11. 怎么用python画皮卡丘_实现童年宝可梦,教你用Python画一只属于自己的皮卡丘
  12. 雅高集团2021年即将开业的新酒店数量强劲增长
  13. 让云助力企业数字化转型
  14. “有”“无”之间的哲学对话——海德格尔与老庄哲学思想的相互阐释
  15. 如何让腾讯微博搜索排名靠前?
  16. 位与,位或,异或,取反
  17. iOS 实现Cordova-Beecloud支付插件
  18. java 访客模式,每日一课 | Java 8中的instanceof运算符和访客模式替换
  19. 高定服装走向NFT,巴黎时装周的数字化将带来什么新趋势?
  20. 映美Jolimark CFP-535G 打印机驱动

热门文章

  1. 用泰勒公式求近似值_满足多个条件求最值,用这2个函数组合,写出来的公式如此简单...
  2. layui让文字和div平行_layui富文本的使用注意事项以及拓展
  3. Javascript:一个屌丝的逆袭之路
  4. 零基础转行自学前端,怎么学习更系统?
  5. 学会这6个强大的CSS选择器,将真正帮你写出干净的CSS代码!
  6. 应该怎么样学习前端呢?
  7. 软件加入使用时间_Mac实用菜单栏管理小工具 Bartender 3 | Mac软件天堂
  8. ggbiplot设置分组_比PCA更好用的监督排序—LDA分析、作图及添加置信-ggord
  9. python爬虫 入门+进阶_python爬虫入门到进阶(三)
  10. php计算单价乘数量,数量单价怎么算出金额