【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
题目描述
傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了。 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决。 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来。在游戏中,幽香可能在空地上增加或者减少一些军队。同时,幽香可以在一个空地上放置一个补给站。 如果补给站在点u上,并且空地v上有dv个单位的军队,那么幽香每天就要花费dv×dist(u,v)的金钱来补给这些军队。由于幽香需要补给所有的军队,因此幽香总共就要花费为Sigma(Dv*dist(u,v),其中1<=V<=N)的代价。其中dist(u,v)表示u个v在树上的距离(唯一路径的权和)。 因为游戏的规定,幽香只能选择一个空地作为补给站。在游戏的过程中,幽香可能会在某些空地上制造一些军队,也可能会减少某些空地上的军队,进行了这样的操作以后,出于经济上的考虑,幽香往往可以移动他的补给站从而省一些钱。但是由于这个游戏的地图是在太大了,幽香无法轻易的进行最优的安排,你能帮帮她吗? 你可以假定一开始所有空地上都没有军队。
输入
输出
对于幽香的每个操作,输出操作完成以后,每天的最小花费,也即如果幽香选择最优的补给点进行补给时的花费。
样例输入
10 5
1 2 1
2 3 1
2 4 1
1 5 1
2 6 1
2 7 1
5 8 1
7 9 1
1 10 1
3 1
2 1
8 1
3 1
4 1
样例输出
0
1
4
5
6
题解
动态点分治
考虑到带权重心一定在当前点到距离与权重总和更小的方向上(没有则当前点为重心),并且这个方向是唯一的,因此可以每次修改都这样移动,把重心找出。
然而直接移动就是直接暴力,需要更优雅的做法。
考虑在子树中移动,可以使用动态点分治的点分树,这样树高只有$\log n$,就可以在每层之间移动重心。
那么只需要想办法求出所有带权点到某个点的距离,并支持修改即可。
由于一个子树以外的点到子树中某点距离可以看作先到根,再从根到该点。所以可以考虑容斥的方法,即用子树中所有点到该点的距离&个数减去子节点的子树中所有点到该点的距离&个数。
然后维护这两个数组即可。由于保证了每个点的度数不超过20,因此每次暴力移动重心,直到所有子节点都比它大为止,此时当前点就是重心。
时间复杂度$O(20n\log^2n)$
- #include <cstdio>
- #include <algorithm>
- #define N 100010
- using namespace std;
- typedef long long ll;
- int head[N] , to[N << 1] , len[N << 1] , next[N << 1] , cnt , log[N << 1] , pos[N] , tot;
- int si[N] , mx[N] , sum , root , vis[N] , fa[N] , val[N << 1] , rt , num[N];
- ll deep[N] , md[20][N << 1] , va[N] , vb[N];
- void add(int x , int y , int z)
- {
- to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
- }
- void dfs(int x , int fa)
- {
- int i;
- pos[x] = ++tot , md[0][tot] = deep[x];
- for(i = head[x] ; i ; i = next[i])
- if(to[i] != fa)
- deep[to[i]] = deep[x] + len[i] , dfs(to[i] , x) , md[0][++tot] = deep[x];
- }
- ll dis(int x , int y)
- {
- ll t = deep[x] + deep[y];
- x = pos[x] , y = pos[y];
- if(x > y) swap(x , y);
- int k = log[y - x + 1];
- return t - 2 * min(md[k][x] , md[k][y - (1 << k) + 1]);
- }
- void getroot(int x , int fa)
- {
- int i;
- si[x] = 1 , mx[x] = 0;
- for(i = head[x] ; i ; i = next[i])
- if(!vis[to[i]] && to[i] != fa)
- getroot(to[i] , x) , si[x] += si[to[i]] , mx[x] = max(mx[x] , si[to[i]]);
- mx[x] = max(mx[x] , sum - si[x]);
- if(mx[x] < mx[root]) root = x;
- }
- void solve(int x)
- {
- int i;
- vis[x] = 1;
- for(i = head[x] ; i ; i = next[i])
- if(!vis[to[i]])
- sum = si[to[i]] , root = 0 , getroot(to[i] , 0) , fa[root] = x , val[i] = root , solve(root);
- }
- ll calc(int x)
- {
- int i;
- ll ans = 0;
- for(i = x ; i ; i = fa[i]) ans += va[i] + num[i] * dis(x , i);
- for(i = x ; fa[i] ; i = fa[i]) ans -= vb[i] + num[i] * dis(x , fa[i]);
- return ans;
- }
- ll query()
- {
- int x = rt , i , y;
- ll mn , t;
- while(1)
- {
- mn = calc(x) , y = x;
- for(i = head[x] ; i ; i = next[i])
- if(val[i] && (t = calc(to[i])) < mn)
- mn = t , y = val[i];
- if(x == y) break;
- x = y;
- }
- return mn;
- }
- int main()
- {
- int n , m , i , j , x , y , z;
- scanf("%d%d" , &n , &m);
- for(i = 1 ; i < n ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , add(x , y , z) , add(y , x , z);
- dfs(1 , 0);
- for(i = 2 ; i <= tot ; i ++ ) log[i] = log[i >> 1] + 1;
- for(i = 1 ; (1 << i) <= tot ; i ++ )
- for(j = 1 ; j <= tot - (1 << i) + 1 ; j ++ )
- md[i][j] = min(md[i - 1][j] , md[i - 1][j + (1 << (i - 1))]);
- mx[0] = 1 << 30 , sum = n , getroot(1 , 0) , rt = root , solve(root);
- while(m -- )
- {
- scanf("%d%d" , &x , &y);
- for(i = x ; i ; i = fa[i]) va[i] += y * dis(x , i) , num[i] += y;
- for(i = x ; fa[i] ; i = fa[i]) vb[i] += y * dis(x , fa[i]);
- printf("%lld\n" , query());
- }
- return 0;
- }
【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治的更多相关文章
- [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)
题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...
- 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治
[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...
- [ZJOI2015]幻想乡战略游戏——动态点分治
[ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...
- P3345 [ZJOI2015]幻想乡战略游戏 动态点分治
\(\color{#0066ff}{ 题目描述 }\) 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越 ...
- ZJOI2015 幻想乡战略游戏 动态点分治_树链剖分_未调完
Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...
- BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)
这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这 ...
- 洛谷P3345 [ZJOI2015]幻想乡战略游戏 [动态点分治]
传送门 调了两个小时,终于过了-- 凭啥人家代码80行我180行啊!!! 谁叫你大括号换行 谁叫你写缺省源 思路 显然,补给点所在的位置就是这棵树的带权重心. 考虑size已知时如何找重心:一开始设答 ...
- bzoj 3924 [Zjoi2015]幻想乡战略游戏——动态点分治(暴力移动找重心)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 度数只有20,所以从一个点暴力枚举其出边,就能知道往哪个方向走. 知道方向之后直接走到 ...
- BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)
题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑dist(x,i)∗a[i]的最 ...
随机推荐
- python_69_内置函数1
#abs()取绝对值 ''' all(iterable) Return True if all elements of the iterable are true (or if the iterabl ...
- 网络编程——UDP协议和通信
第1章 UDP与TCP协议 在介绍TCP/IP结构时,提到传输层的两个重要的高级协议,分别是UDP和TCP,其中UDP是User Datagram Protocol的简称,称为用户数据报协议,TCP是 ...
- SQLyog点击“测试连接”后,报2058错误
问题:安装MySQL和SQLyog之后,在SQLyog中点击“测试连接”时,报2058错误. 解决:这里要确定两个问题:1 MySQL是否配置了环境变量:2 如果配置了MySQL环境变量,那么需要在c ...
- 三十四、MySQL 函数
MySQL 函数 MySQL 有很多内置的函数,以下列出了这些函数的说明. MySQL 字符串函数 函数 描述 实例 ASCII(s) 返回字符串 s 的第一个字符的 ASCII 码. 返回 Cust ...
- 重置 nexus3 admin 密码
2 简单 3 重构,变化很大 如何处理nexus3忘记admin密码 - CSDN博客 https://blog.csdn.net/tianya6607/article/details/5330562 ...
- nodeJS 服务端文件上传
var http = require('http'); var path = require('path'); var fs = require('fs'); function uploadFile( ...
- 判断浏览器环境(QQ,微信,安卓设备,IOS设备,PC微信环境,移动设备)
判断浏览器环境(QQ,微信,安卓设备,IOS设备,PC微信环境,移动设备) // ===== 判断浏览器环境 ===== // // 判断是否是QQ环境 function isQQ() { retur ...
- thinkphp 3.2.3 - Dispatcher.class.php 解析(转发器)
class Dispatcher { public static function dispatch() { $varPath = C('VAR_PATHINFO'); // 's' $varAddo ...
- Android Studio 3.0 安装注意点
在安装Android studio 3.0+ 时候,会遇到默认不带Android SDK 的问题. 在启动Android studio 后,会提示让选择SDK目录,选择下载目录,对应的去下载 那么问题 ...
- MongDB之各种修改操作
接口IMongDaoUpdate: package com.net.test.mongdb.dao; import com.net.test.mongdb.entity.User; public in ...