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

problem

luogu-P3340

题面写得那么长,其实说白了就是求一条直线,使得若干个点到这条直线的距离平方的和最小,求这个最小值。

solution

我超爱数学,数学就是我的命,我一天不学数学我就难受!

假设拟合出的直线为:y=kx+by=kx+by=kx+b

点到直线 Ax0+By0+C=0Ax_0+By_0+C=0Ax0+By0+C=0 的距离公式:d=∣Ax+By+C∣A2+B2d=\frac{|Ax+By+C|}{\sqrt{A^2+B^2}}d=A2+B2Ax+By+C 不会就去问数学老师

接下来就是推式子:
∑(kxi−yi+b)2k2+1=∑k2xi2+yi2+b2−2kxiyi+2kbxi−2byik2+1\frac{\sum(kx_i-y_i+b)^2}{k^2+1}=\frac{\sum k^2x_i^2+y_i^2+b^2-2kx_iy_i+2kbx_i-2by_i}{k^2+1} k2+1(kxiyi+b)2=k2+1k2xi2+yi2+b22kxiyi+2kbxi2byi
xi,yix_i,y_ixi,yi 都可被视作已知量,所以只有 k,bk,bk,b 是未知数。

答案要最小化这个式子的值,k,bk,bk,b 没有任何等量关系,所以我们两个各自最小化即可。

先最小化 bbb 的求值,把 kkk 假想成已知量。
=∑(b2+(2kxi−2yi)b+yi2−2kxiyi+k2xi2)k2+1=nb2+∑(2kxi−2yi)b+∑(yi2−2kxiyi+k2xi2)k2+1=\frac{\sum(b^2+(2kx_i-2y_i)b+y_i^2-2kx_iy_i+k^2x_i^2)}{k^2+1}=\frac{nb^2+\sum(2kx_i-2y_i)b+\sum(y_i^2-2kx_iy_i+k^2x_i^2)}{k^2+1} =k2+1(b2+(2kxi2yi)b+yi22kxiyi+k2xi2)=k2+1nb2+(2kxi2yi)b+(yi22kxiyi+k2xi2)
显然这是个关于 bbb 的二次函数。根据数学知识,我们知道当 b=∑(2yi−2kxi)2nb=\frac{\sum(2y_i-2kx_i)}{2n}b=2n(2yi2kxi) 时取到最低点。

b=∑(2yi−2kxi)2n=∑yi−k∑xinb=\frac{\sum(2y_i-2kx_i)}{2n}=\frac{\sum y_i-k\sum x_i}{n}b=2n(2yi2kxi)=nyikxi,恰好发现 ∑xin=xˉ\frac{\sum x_i}{n}=\bar{x}nxi=xˉ(平均数),∑yin=yˉ\frac{\sum y_i}{n}=\bar{y}nyi=yˉ

然后现在把 bbb 当作常量 b=yˉ−kxˉb=\bar{y}-k\bar{x}b=yˉkxˉ,把 kkk 当作未知数。
=n(yˉ−kxˉ)2+∑(2kxi−2yi)(yˉ−kxˉ)+∑(yi2−2kxiyi+k2xi2)k2+1=\frac{n(\bar{y}-k\bar{x})^2+\sum(2kx_i-2y_i)(\bar{y}-k\bar{x})+\sum(y_i^2-2kx_iy_i+k^2x_i^2)}{k^2+1} =k2+1n(yˉkxˉ)2+(2kxi2yi)(yˉkxˉ)+(yi22kxiyi+k2xi2)

=nyˉ2−2nkxˉyˉ+nk2xˉ2+∑(2kxiyˉ−2yiyˉ−2k2xixˉ+2yikxˉ)+∑(yi2−2kxiyi+k2xi2)k2+1=\frac{n\bar{y}^2-2nk\bar{x}\bar{y}+nk^2\bar{x}^2+\sum(2kx_i\bar{y}-2y_i\bar{y}-2k^2x_i\bar{x}+2y_ik\bar{x})+\sum(y_i^2-2kx_iy_i+k^2x_i^2)}{k^2+1} =k2+1nyˉ22nkxˉyˉ+nk2xˉ2+(2kxiyˉ2yiyˉ2k2xixˉ+2yikxˉ)+(yi22kxiyi+k2xi2)

=∑(xˉ2−2xixˉ+xi2)k2+∑(−2xˉyˉ+2xiyˉ+2yixˉ−2xiyi)k+∑(yˉ2−2yiyˉ+yi2)k2+1=\frac{\sum(\bar{x}^2-2x_i\bar{x}+x_i^2)k^2+\sum(-2\bar{x}\bar{y}+2x_i\bar{y}+2y_i\bar{x}-2x_iy_i)k+\sum(\bar{y}^2-2y_i\bar{y}+y_i^2)}{k^2+1} =k2+1(xˉ22xixˉ+xi2)k2+(2xˉyˉ+2xiyˉ+2yixˉ2xiyi)k+(yˉ22yiyˉ+yi2)

为了式子的简洁美观,我们记:
{A=∑xˉ2−∑2xix+∑xi2B=−2nxˉyˉ+∑2xiyˉ+∑2yixˉ−∑2xiyiC=nyˉ2−∑2yiyˉ+∑yi2\begin{cases} A=\sum\bar{x}^2-\sum 2x_ix+\sum x_i^2\\ B=-2n\bar{x}\bar{y}+\sum 2x_i\bar{y}+\sum2y_i\bar{x}-\sum2x_iy_i\\ C=n\bar{y}^2-\sum2y_i\bar{y}+\sum y_i^2 \end{cases} A=xˉ22xix+xi2B=2nxˉyˉ+2xiyˉ+2yixˉ2xiyiC=nyˉ22yiyˉ+yi2
则有 Ak2+Bk+Ck2+1→ans\frac{Ak^2+Bk+C}{k^2+1}\rightarrow ansk2+1Ak2+Bk+Cans
ans=Ak2+Bk+Ck2+1⇒ans(k2+1)=Ak2+Bk+C⇒(A−ans)k2+Bk+C−ans=0ans=\frac{Ak^2+Bk+C}{k^2+1}\Rightarrow ans(k^2+1)=Ak^2+Bk+C\Rightarrow (A-ans)k^2+Bk+C-ans=0 ans=k2+1Ak2+Bk+Cans(k2+1)=Ak2+Bk+C(Aans)k2+Bk+Cans=0
因为题目肯定是有解的,所以这个二元一次方程要有根,即 Δ≥0\Delta\ge 0Δ0
KaTeX parse error: Undefined control sequence: \ at position 75: …ns+B^2-4AC\ge 0\̲ ̲
又得到了一个关于 ansansans 的开口向下的二次函数,ansansans 最小取值就是其方程的较小根,再用一次求根公式即可。

所以我们只需要维护 n,∑xi,∑yi,∑xi2,∑yi2,∑xiyin,\sum x_i,\sum y_i,\sum x_i^2,\sum y_i^2,\sum x_iy_in,xi,yi,xi2,yi2,xiyi 这几个信息。

一条路径上的信息维护,发现树上差分即可做到,记从根到该点一路上的信息之和。

基环树存一下环的点,然后把环拍成链,考虑有两种走环的方式,比较最小值即可。

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 100005
struct node {int n, sumx, sumy, sumx2, sumy2, sumxy;void insert( int x, int y ) { n ++, sumx += x, sumy += y, sumx2 += x * x, sumy2 += y * y, sumxy += x * y; }double calc() {double var_x = sumx * 1.0 / n, var_y = sumy * 1.0 / n;double A = sumx2 - 2 * var_x * sumx + n * var_x * var_x;double B = - 2 * sumxy + 2 * sumx * var_y + 2 * sumy * var_x - 2 * n * var_x * var_y;double C = sumy2 - 2 * sumy * var_y + n * var_y * var_y;double a = 4, b = - 4 * ( A + C ), c = 4 * A * C - B * B;double delta = sqrt( b * b - 4 * a * c );return ( - b - delta ) / ( 2 * a );}
}f[maxn], g[maxn];
node operator + ( node HM, node NB ) { HM.n += NB.n, HM.sumx += NB.sumx, HM.sumy += NB.sumy, HM.sumx2 += NB.sumx2, HM.sumy2 += NB.sumy2, HM.sumxy += NB.sumxy; return HM; }
node operator - ( node HM, node NB ) { HM.n -= NB.n, HM.sumx -= NB.sumx, HM.sumy -= NB.sumy, HM.sumx2 -= NB.sumx2, HM.sumy2 -= NB.sumy2, HM.sumxy -= NB.sumxy; return HM; }
struct point { int x, y; }p[maxn];
int n, m, Q, cnt;
int fa[maxn], dep[maxn], top[maxn], root[maxn], vis[maxn], siz[maxn], son[maxn], num[maxn], circle[maxn];
vector < int > G[maxn];int lca( int u, int v ) {while( top[u] ^ top[v] )if( dep[top[u]] < dep[top[v]] ) v = fa[top[v]];else u = fa[top[u]];return dep[u] < dep[v] ? u : v;
}void dfs1( int u, int rt ) {root[u] = rt, siz[u] = vis[u] = 1, son[u] = 0;f[u] = f[fa[u]], f[u].insert( p[u].x, p[u].y );for( int v : G[u] ) if( ! vis[v] and v ^ fa[u] ) {fa[v] = u;dep[v] = dep[u] + 1;dfs1( v, rt );siz[u] += siz[v];if( siz[son[u]] < siz[v] ) son[u] = v;}
}void dfs2( int u, int t ) {top[u] = t;if( son[u] ) dfs2( son[u], t );else return;for( int v : G[u] )if( fa[v] == u and son[u] ^ v ) dfs2( v, v );
}void work() {for( int u = 1;u <= n;u ++ )for( int v : G[u] )if( fa[v] ^ u and fa[u] ^ v ) {if( dep[u] > dep[v] ) swap( u, v );while( v ^ u ) {circle[++ cnt] = v;num[v] = cnt;g[cnt] = g[cnt - 1];g[cnt].insert( p[v].x, p[v].y );vis[v] = 1;	v = fa[v];}circle[++ cnt] = u;num[u] = cnt;g[cnt] = g[cnt - 1];g[cnt].insert( p[u].x, p[u].y );vis[u] = 1;return;} 
}int main() {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ ) scanf( "%d %d", &p[i].x, &p[i].y );for( int i = 1, u, v;i <= m;i ++ ) {scanf( "%d %d", &u, &v );G[u].push_back( v );G[v].push_back( u );}dfs1( 1, 1 );memset( vis, 0, sizeof( vis ) );if( n == m ) work();else circle[cnt = 1] = 1;memset( fa, 0, sizeof( fa ) );for( int i = 1;i <= cnt;i ++ ) dfs1( circle[i], circle[i] ), dfs2( circle[i], circle[i] );scanf( "%d", &Q );while( Q -- ) {int x, y;scanf( "%d %d", &x, &y );if( root[x] == root[y] )printf( "%.5f\n", (f[x] + f[y] - f[lca( x, y )] - f[fa[lca( x, y )]] ).calc() );else {if( num[root[x]] > num[root[y]] ) swap( x, y );node u = f[x] - f[root[x]] + f[y] - f[root[y]] + g[num[root[y]]] - g[num[root[x]] - 1];node v = f[x] - f[root[x]] + f[y] - f[root[y]] + g[num[root[x]]] + g[cnt] - g[num[root[y]] - 1];printf( "%.5f\n", min( u.calc(), v.calc() ) );}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316447.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[ZJOI2014] 璀璨光华(bfs建图 + dfs搜索)

problem luogu-P3342 solution 你感觉这道题没考什么&#xff0c;又感觉考了什么 通过样例以及题面&#xff0c;我们并未获取到『立方体每个小方块的编号是按一定规则命名』的信息。 也就是说&#xff0c;我们需要通过输入的每个小方块相邻的编号的信息来建出这个立方体的…

cf1523A. Game of Life

cf1523A. Game of Life 题意&#xff1a; 包含n个元素的数组&#xff0c;数值为1或0&#xff0c;如果一个元素为0&#xff0c;并且其周围正好只有一个为1的元素&#xff0c;那么下一刻本元素也会变成1. 给你一个数值&#xff0c;问你m次时刻后数组的状态 题解&#xff1a; …

SignalR 中丰富多彩的消息推送方式

在上一篇 SignalR 文章中&#xff0c;演示了如何通过 SignalR 实现了简单的聊天室功能&#xff1b;本着简洁就是美的原则&#xff0c;这一篇我们也来聊聊在 SignalR 中的用户和组的概念&#xff0c;理解这些基础知识有助于更好的开发基于 SignalR 的应用&#xff0c;通过对用户…

Visual Studio 2019 使用 Live Share

一.前言Visual Studio 2019 在今天发布&#xff08;北京时间&#xff09;了&#xff0c;这次带来了一个比较有趣的 Live Share 功能&#xff0c;使用它可以进行更好的协作开发。主要功能&#xff1a;更多资料可看官方介绍&#xff1a;Visual Studio 实时共享什么是Visual Studi…

cf1523B. Lord of the Values

cf1523B. Lord of the Values 题意&#xff1a; 给你一个数组&#xff0c;有n个数&#xff0c;n为偶数&#xff0c;a1&#xff0c;a2…an 现在有两个操作&#xff1a; 对于i<j 操作1&#xff1a;aiaiaj 操作2&#xff1a;ajaj-ai 把原数组转换为-a1,-a2,-a3… 题解&#…

Asp.Net Core WebAPI使用Swagger时API隐藏与分组

1、前言为什么我们要隐藏部分接口&#xff1f;因为我们在用swagger代替接口的时候&#xff0c;难免有些接口会直观的暴露出来&#xff0c;比如我们结合Consul一起使用的时候&#xff0c;会将健康检查接口以及报警通知接口暴露出来&#xff0c;这些接口有时候会出于方便考虑&…

cf1526E. Oolimry and Suffix Array(未解决)

E. Oolimry and Suffix Array 题意&#xff1a; 给定n&#xff0c;k和长度为n的后缀数组si(0<si<n-1),求长度为n的由k种字母构成的字符串种&#xff0c;后缀数组为si的有多少种 题解&#xff1a; 题解看懂了一半。。。等会了再更新 代码&#xff1a;

P2572 [SCOI2010]序列操作

P2572 [SCOI2010]序列操作 题意&#xff1a; 一个长度为n的01序列&#xff0c;下标从0开始&#xff0c;现在有五种变换操作和询问操作&#xff1a; 0 l r 把[l,r]区间内的所有数全变成01 l r 把[l,r]区间内的所有数全变成12 l r把[l,]区间内所有数全部取反3 l r询问[l,r]区间…

为您的机器配置开发环境

软件准备在本期视频中&#xff0c;我们将安装所序言的软件&#xff0c;并为我们的电脑配置.NET Core开发环境。我们需要安装如下2个软件&#xff1a;一个编辑器.NET Core SDK&#xff08;Software Development Kit&#xff09;下载并安装.NET Core 开发编辑器我的是Windows操作…

[CQOI2012] 局部极小值(状压DP + 容斥 + 搜索)

problem luogu-P3160 solution 这么小的数据范围&#xff0c;非暴力不状压。暴力 O(28!)O(28!)O(28!) 呵呵呵可以拉走了。 我们不妨从小到大填数字&#xff0c;这样如果局部极小值点还没有填的话&#xff0c;周围的九宫格就一定不能被填。 设 dp(s,i):dp(s,i):dp(s,i): 局…

基于Kubernetes 构建.NET Core 的技术体系

很多公司技术支持岗位的工作&#xff0c;如配置域名&#xff0c;部署环境&#xff0c;修改复位配置&#xff0c;服务重启&#xff0c;扩容缩容&#xff0c;梳理和完善监控&#xff0c;根据开发的需要查找日志等工作&#xff0c;需要和开发进行大量的沟通&#xff0c;如什么是外…

P4062 [Code+#1]Yazid 的新生舞会(分治做法)

P4062 [Code#1]Yazid 的新生舞会 题意&#xff1a; 给出一个序列&#xff0c;求有多少个子区间满足众数的出现次数大于区间长度的一半。 出现次数大于区间长度的一般我们称之为绝对众数 题解&#xff1a; 分治做法 对于一个区间[l,r]&#xff0c;设mid⌊lr2⌋\lfloor \frac…

[CQOI2014] 危桥(网络流)

problem luogu-P3163 solution 这是一道网络流好题&#xff0c;看的着摸不着吃不着。 初读完题&#xff0c;就知道这是一道“脱光了”的最大流。 建图基础版本&#xff1a; 建立额外源汇点。 无向边相同于两条有向边&#xff0c;直接建不影响&#xff0c;危桥流量设成 22…

那些优秀的开发者----汪宇杰:从重视细节,到成就技术专家

汪宇杰&#xff08;Edi Wang&#xff09;&#xff0c;.NET及Windows开发者&#xff0c;2018-2019年度微软最有价值专家&#xff08;Windows Development方向&#xff09;。现担任某金融科技企业的网站开发工程师。他对微软技术有鉴定的信念和不灭的热情&#xff0c;曾在Windows…

P4062 [Code+#1]Yazid 的新生舞会(线段树做法)

P4062 [Code#1]Yazid 的新生舞会&#xff08;线段树做法&#xff09; 题意&#xff1a; 给你一个序列a[1…n]​&#xff0c;求存在绝对众数的子区间个数。 绝对众数指&#xff1a;区间中出现次数最多的那个数&#xff0c;出现次数严格大于区间长度的一半。 题解&#xff1a…

《从零开始学ASP.NET CORE MVC》课程介绍

大家好&#xff0c;欢迎来到52ABP学院&#xff0c;收看我们的 《从零开始学ASP.NET CORE MVC》。ASP.NET Core 简介从2015年开始随时互联网成长&#xff0c;云计算和AI、大数据的爆发&#xff0c;大家从谈论项目信息化到数字化的转型&#xff0c;从ToC产业到ToB产业的转型&…

[ZJOI2015] 地震后的幻想乡(状压dp + 期望)

problem luogu-P3343 solution dp(i):dp(i):dp(i): 当恰好加入第 iii 小边时候&#xff0c;所有点联通的方案数。 则 ans∑idpi(mi)im1ans\sum_i \frac{dp_i}{\binom mi}\frac{i}{m1}ans∑i​(im​)dpi​​m1i​ 。 重点是如何计算出 dp(i)dp(i)dp(i)。 这个恰好的限制不好…

P2152 [SDOI2009]SuperGCD

P2152 [SDOI2009]SuperGCD 题意&#xff1a; 求a和b的最大公约数 a,b<101000010^{10000}1010000 题解&#xff1a; 高精度&#xff0c;java高精度直接有模板&#xff0c;c高精度结合gcd的辗转相减法 对于&#xff1a;a,b的gcd(a,b)有&#xff1a; 若a为奇数&#xff0c…

Docker - 容器部署 Consul 集群

目录 准备 Consul 镜像安装单个 Consul组装集群 Consul启动 Consul 和 Web 管理器Consul 命令简单介绍Web 管理器Server 加入集群Client 加入集群了解 ConsulConsul 使用场景Consul 优势Consul 中的概念说明简介安装总结引用和附件说明本文主要介绍怎么使用 Docker 在 Linux…

[LOJ3153] 三级跳(单调栈 + 线段树)

problem loj3153 solution 有一个显然正确但又不起眼却是正解必备的结论&#xff1a; 考虑 (x,y,z)(x,y,z)(x,y,z) 答案三元对&#xff0c;如果有一个数 i∈(x,y)∧ai≥axi\in(x,y)\wedge a_i\ge a_xi∈(x,y)∧ai​≥ax​&#xff0c;那么 (i,y,z)(i,y,z)(i,y,z) 一定是不劣…