[ZJOI2015] 幻想乡战略游戏

本文详细介绍了如何解决ZJOI2015中的一道名为“幻想乡战略游戏”的题目。通过分析,作者指出该问题的关键在于利用重心思想,并结合点分树进行求解。点分树的高度和度数特性确保了算法的时间复杂度为O(nlog3n)。文章解释了如何在点分树上暴力查找答案,并强调了理解点分树分治子树与原树差异的重要性,同时提供了维护答案的方法。
摘要由CSDN通过智能技术生成

一、题目

点此看题

二、解法

本来以为这个题就是个垃圾题,结果是我没理解到,我是傻逼。

首先你看到这种最小化距离的题一定要想到重心,这道题其实也是重心鸭。你把 d u d_u du 看成节点 u u u 上的真点个数,那么取这些真点在图上面的重心就是最小化的距离。

由于最近在学点分树,就想到了用点分树的角度来思考这道题。这里有两个关键的条件:点分树的树高是 log ⁡ n \log n logn 级别的,点分树的度数也是 20 20 20(相当于 log ⁡ n \log n logn 级别的)

那么就想到在点分树上暴力找,不知道在哪里,那就从根开始,由于真点的重心只有一个,所以如果我们要移动当前的答案那么至多只会走向一个分治子树,这就是复杂度的保证。

判断重心在哪个子树的方法可以推柿子,但是那东西有点难维护,这里又涉及到了对点分治的理解。他所能维护的是管辖范围内的点而不是原树上的点,所以有些东西是不能维护的。

介绍一种暴力判断的方法,你找到分治子树在原树上直接相邻的节点考虑向他移动,如果答案更优那么重心一定在这个分治子树内,我们至多只会移动到一个子树(因为至多只有一个方向答案是减少的),现在你一定会点分治有了更深的理解,所谓分治子树只是保证复杂度的一种方式,而不要把他当作原树一般看待。

统计答案是有手就行的,做过板题震波的同学都知道我们要维护分治子树内的点到当前点的总贡献 s [ u ] s[u] s[u],分治子树内的点到 u u u 的分治父亲的总贡献 f s [ u ] fs[u] fs[u],再维护分治子树内的真点数 s d [ u ] sd[u] sd[u],那么假设算的是 x x x 的答案,要把 ( x , i ) (x,i) (x,i) 的距离考虑进去就行了( i i i 是当前跳到的结点)

时间复杂度 O ( n log ⁡ 3 n ) O(n\log ^3n) O(nlog3n),点分树的代码都很好写鸭。

#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
const int M = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值