IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> [ZJOI2014] 星系调查(树上差分 + 数学推式子) -> 正文阅读

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

problem

luogu-P3340

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

solution

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

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

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

接下来就是推式子:
∑ ( k x i ? y i + b ) 2 k 2 + 1 = ∑ k 2 x i 2 + y i 2 + b 2 ? 2 k x i y i + 2 k b x i ? 2 b y i k 2 + 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(kxi??yi?+b)2?=k2+1k2xi2?+yi2?+b2?2kxi?yi?+2kbxi??2byi??
x i , y i x_i,y_i xi?,yi? 都可被视作已知量,所以只有 k , b k,b k,b 是未知数。

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

先最小化 b b b 的求值,把 k k k 假想成已知量。
= ∑ ( b 2 + ( 2 k x i ? 2 y i ) b + y i 2 ? 2 k x i y i + k 2 x i 2 ) k 2 + 1 = n b 2 + ∑ ( 2 k x i ? 2 y i ) b + ∑ ( y i 2 ? 2 k x i y i + k 2 x i 2 ) k 2 + 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+(2kxi??2yi?)b+yi2??2kxi?yi?+k2xi2?)?=k2+1nb2+(2kxi??2yi?)b+(yi2??2kxi?yi?+k2xi2?)?
显然这是个关于 b b b 的二次函数。根据数学知识,我们知道当 b = ∑ ( 2 y i ? 2 k x i ) 2 n b=\frac{\sum(2y_i-2kx_i)}{2n} b=2n(2yi??2kxi?)? 时取到最低点。

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

然后现在把 b b b 当作常量 b = y ˉ ? k x ˉ b=\bar{y}-k\bar{x} b=yˉ??kxˉ,把 k k k 当作未知数。
= n ( y ˉ ? k x ˉ ) 2 + ∑ ( 2 k x i ? 2 y i ) ( y ˉ ? k x ˉ ) + ∑ ( y i 2 ? 2 k x i y i + k 2 x i 2 ) k 2 + 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+(2kxi??2yi?)(yˉ??kxˉ)+(yi2??2kxi?yi?+k2xi2?)?

= n y ˉ 2 ? 2 n k x ˉ y ˉ + n k 2 x ˉ 2 + ∑ ( 2 k x i y ˉ ? 2 y i y ˉ ? 2 k 2 x i x ˉ + 2 y i k x ˉ ) + ∑ ( y i 2 ? 2 k x i y i + k 2 x i 2 ) k 2 + 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ˉ?2?2nkxˉyˉ?+nk2xˉ2+(2kxi?yˉ??2yi?yˉ??2k2xi?xˉ+2yi?kxˉ)+(yi2??2kxi?yi?+k2xi2?)?

= ∑ ( x ˉ 2 ? 2 x i x ˉ + x i 2 ) k 2 + ∑ ( ? 2 x ˉ y ˉ + 2 x i y ˉ + 2 y i x ˉ ? 2 x i y i ) k + ∑ ( y ˉ 2 ? 2 y i y ˉ + y i 2 ) k 2 + 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ˉ2?2xi?xˉ+xi2?)k2+(?2xˉyˉ?+2xi?yˉ?+2yi?xˉ?2xi?yi?)k+(yˉ?2?2yi?yˉ?+yi2?)?

为了式子的简洁美观,我们记:
{ A = ∑ x ˉ 2 ? ∑ 2 x i x + ∑ x i 2 B = ? 2 n x ˉ y ˉ + ∑ 2 x i y ˉ + ∑ 2 y i x ˉ ? ∑ 2 x i y i C = n y ˉ 2 ? ∑ 2 y i y ˉ + ∑ y i 2 \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ˉ2?2xi?x+xi2?B=?2nxˉyˉ?+2xi?yˉ?+2yi?xˉ?2xi?yi?C=nyˉ?2?2yi?yˉ?+yi2??
则有 A k 2 + B k + C k 2 + 1 → a n s \frac{Ak^2+Bk+C}{k^2+1}\rightarrow ans k2+1Ak2+Bk+C?ans
a n s = A k 2 + B k + C k 2 + 1 ? a n s ( k 2 + 1 ) = A k 2 + B k + C ? ( A ? a n s ) k 2 + B k + C ? a n s = 0 ans=\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+C??ans(k2+1)=Ak2+Bk+C?(A?ans)k2+Bk+C?ans=0
因为题目肯定是有解的,所以这个二元一次方程要有根,即 Δ ≥ 0 \Delta\ge 0 Δ0
KaTeX parse error: Undefined control sequence: \ at position 75: …ns+B^2-4AC\ge 0\? ?
又得到了一个关于 a n s ans ans 的开口向下的二次函数, a n s ans ans 最小取值就是其方程的较小根,再用一次求根公式即可。

所以我们只需要维护 n , ∑ x i , ∑ y i , ∑ x i 2 , ∑ y i 2 , ∑ x i y i n,\sum x_i,\sum y_i,\sum x_i^2,\sum y_i^2,\sum x_iy_i n,xi?,yi?,xi2?,yi2?,xi?yi? 这几个信息。

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

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

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;
}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 22:09:00  更:2022-03-13 22:09:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/24 3:39:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计