[ZJOI 2015]幻想乡战略游戏
Description
傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了。 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决。 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来。在游戏中,幽香可能在空地上增加或者减少一些军队。同时,幽香可以在一个空地上放置一个补给站。 如果补给站在点u上,并且空地v上有dv个单位的军队,那么幽香每天就要花费dv×dist(u,v)的金钱来补给这些军队。由于幽香需要补给所有的军队,因此幽香总共就要花费为Sigma(Dv*dist(u,v),其中1<=V<=N)的代价。其中dist(u,v)表示u个v在树上的距离(唯一路径的权和)。 因为游戏的规定,幽香只能选择一个空地作为补给站。在游戏的过程中,幽香可能会在某些空地上制造一些军队,也可能会减少某些空地上的军队,进行了这样的操作以后,出于经济上的考虑,幽香往往可以移动他的补给站从而省一些钱。但是由于这个游戏的地图是在太大了,幽香无法轻易的进行最优的安排,你能帮帮她吗? 你可以假定一开始所有空地上都没有军队。
Input
Output
对于幽香的每个操作,输出操作完成以后,每天的最小花费,也即如果幽香选择最优的补给点进行补给时的花费。
Sample Input
1 2 1
2 3 1
2 4 1
1 5 1
2 61
2 7 1
5 8 1
7 91
1 10 1
3 1
2 1
8 1
3 1
4 1
Sample Output
1
4
5
6
题解
其实和[HNOI 2015]开店的动态点分统计答案的方法类似,不再赘述。
这里主要讲如何找到“带权重心”。
我们每次从点分的根开始遍历与它相邻的所有点,统计出他们的答案,值得肯定的是这些值只会存在两种情况:
1. 相邻的所有值都大于这个点的答案,显然这个点就是要求的点;
2. 相邻的点只有一个的值,小于这个点统计出的答案,就直接向这棵更小的子树走,注意是走到“分治树”的下一个重心,继续操作。
//It is made by Awson on 2018.1.9
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define lowbit(x) ((x)&(-(x)))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
using namespace std;
const int N = 1e5;
const int INF = ~0u>>;
void read(int &x) {
char ch; bool flag = ;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || ); ch = getchar());
for (x = ; isdigit(ch); x = (x<<)+(x<<)+ch-, ch = getchar());
x *= -*flag;
} int n, q, u, v, c, fa[N+], G;
LL sum[N+], dis1[N+], dis2[N+];
struct tt {
int to, next, cost;
}G1edge[(N<<)+], G2edge[N+];
int G1path[N+], G1top, G2path[N+], G2top;
void G1add(int u, int v, int c) {
G1edge[++G1top].to = v, G1edge[G1top].cost = c, G1edge[G1top].next = G1path[u], G1path[u] = G1top;
}
void G2add(int u, int v, int c) {
G2edge[++G2top].to = v, G2edge[G2top].cost = c, G2edge[G2top].next = G2path[u], G2path[u] = G2top;
}
namespace LCA {
int lim, bin[], dfn[N+], tim, logn[(N<<)+];
LL f[(N<<)+][];
void dfs(int o, LL cost, int father) {
f[dfn[o] = ++tim][] = cost;
for (int i = G1path[o]; i; i = G1edge[i].next)
if (G1edge[i].to != father) dfs(G1edge[i].to, cost+G1edge[i].cost, o), f[++tim][] = cost;
}
LL query(int x, int y) {
if (dfn[x] > dfn[y]) Swap(x, y);
int lim = logn[dfn[y]-dfn[x]+];
return Min(f[dfn[x]][lim], f[dfn[y]-bin[lim]+][lim]);
}
LL dist(int x, int y) {return f[dfn[x]][]+f[dfn[y]][]-(query(x, y)<<); }
void main() {
lim = log(n<<)/log(); bin[] = ; for (int i = ; i <= ; i++) bin[i] = bin[i-]<<;
logn[] = -; for (int i = ; i <= (n<<); i++) logn[i] = logn[i>>]+;
dfs(, , );
for (int t = ; t <= lim; t++) for (int i = ; i+bin[t]- <= (n<<); i++) f[i][t] = Min(f[i][t-], f[i+bin[t-]][t-]);
}
}
namespace Point_divide {
int size[N+], mx[N+], vis[N+], minsize, root;
void get_size(int o, int fa) {
size[o] = , mx[o] = ;
for (int i = G1path[o]; i; i = G1edge[i].next)
if (G1edge[i].to != fa && !vis[G1edge[i].to]) {
get_size(G1edge[i].to, o);
size[o] += size[G1edge[i].to];
if (size[G1edge[i].to] > mx[o]) mx[o] = size[G1edge[i].to];
}
}
void get_root(int o, int pa, int fa) {
mx[o] = Max(mx[o], size[pa]-size[o]);
if (minsize > mx[o]) minsize = mx[o], root = o;
for (int i = G1path[o]; i; i = G1edge[i].next)
if (G1edge[i].to != fa && !vis[G1edge[i].to]) get_root(G1edge[i].to, pa, o);
}
void work(int o, int pa) {
minsize = INF; get_size(o, ), get_root(o, o, );
vis[root] = ; fa[root] = pa; int rt = root; G2add(pa, root, o);
for (int i = G1path[root]; i; i = G1edge[i].next)
if (!vis[G1edge[i].to]) work(G1edge[i].to, rt);
G = rt;
}
void main() {work(, ); }
} void update(int o, int c) {
for (int x = o; x; x = fa[x]) {
sum[x] += c;
dis1[x] += (LL)c*LCA::dist(x, o);
if (fa[x]) dis2[x] += (LL)c*LCA::dist(fa[x], o);
}
}
LL get_ans(int o) {
LL ans = ;
for (int x = o; x; x = fa[x]) {
ans += dis1[x]+sum[x]*LCA::dist(x, o);
if (fa[x]) ans -= sum[x]*LCA::dist(fa[x], o)+dis2[x];
}
return ans;
}
LL query(int o) {
LL ans = get_ans(o);
for (int i = G2path[o]; i; i = G2edge[i].next) {
LL tmp = get_ans(G2edge[i].cost);
if (tmp < ans) return query(G2edge[i].to);
}
return ans;
}
void work() {
read(n), read(q);
for (int i = ; i < n; i++) read(u), read(v), read(c), G1add(u, v, c), G1add(v, u, c);
LCA::main(); Point_divide::main();
while (q--) {
read(u), read(c); update(u, c);
printf("%lld\n", query(G));
}
}
int main() {
work();
return ;
}
[ZJOI 2015]幻想乡战略游戏的更多相关文章
- ZJOI 2015 幻想乡战略游戏(动态点分治)
题意 https://loj.ac/problem/2135 思路 首先要明确一点,答案分布是有单调性的.什么意思呢?假设我们的答案在 \(u\) 节点,\((u,v)\) 之间有一条边且 \(u\) ...
- 解题:ZJOI 2015 幻想乡战略游戏
题面 神**所有点都爆int,我还以为我写出什么大锅了,不开long long见祖宗... 动态点分治利用点分树树高不超过log的性质,我们对每个点维护一个子树和,一个点分树子树和,一个点分树上父亲的 ...
- 【BZOJ3924】幻想乡战略游戏(动态点分治)
[BZOJ3924]幻想乡战略游戏(动态点分治) 题面 权限题...(穷死我了) 洛谷 题解 考虑不修改 发现一个贪心的做法 假设当前放在当前位置 如果它有一个子树的兵的总数大于总数的一半 那么,放到 ...
- LOJ2135 「ZJOI2015」幻想乡战略游戏
题意 题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和 ...
- LOJ #2135. 「ZJOI2015」幻想乡战略游戏
#2135. 「ZJOI2015」幻想乡战略游戏 链接 分析: 动态点分治,求加权重心,带修改. 考虑如果知道了一个点s,如何求答案,那么首先可以点分治的思想,求每个联通块内所有点到分治中心距离和,然 ...
- 洛谷 P3345 [ZJOI2015]幻想乡战略游戏 解题报告
P3345 [ZJOI2015]幻想乡战略游戏 题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做 ...
- [ZJOI2015]幻想乡战略游戏——动态点分治
[ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...
- BZOJ3924 ZJOI2015 幻想乡战略游戏 【动态点分治】
BZOJ3924 ZJOI2015 幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂 ...
- AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345
[ZJOI2015]幻想乡战略游戏 思路: 树剖暴力转移: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...
随机推荐
- AWS EMR上搭建HBase环境
0. 概述 AWS的EMR服务为客户提供的托管 Hadoop 框架可以让您轻松.快 速.经济高效地在多个动态可扩展的 Amazon EC2 实例之间分发和处理 大量数据.您还可以运行其他常用的分发框架 ...
- hp MSA50 5盘RAID5重建为4盘RAID5怎么恢复数据
[用户单位] XX省电视台[数据恢复故障描述] 一台HP 服务器,挂接一台HP MSA50磁盘阵列,内接5块1TB硬盘,原先结构为RAID5. 使用一段时间后,其中一块硬盘掉线,因RAID5支持一块硬 ...
- python之路--day11---迭代器和生成器
迭代: 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 为什么要有迭代器: 数据类型的取值,字符串,列表,元组依靠索引可以取值,但是字典,集合,文件这些数据类型无法 ...
- [JCIP笔记] (二)当我们谈线程安全时,我们在谈论什么
总听组里几个大神说起线程安全问题.本来对"线程安全"这个定义拿捏得就不是很准,更令人困惑的是,大神们用这个词指代的对象不仅抽象而且千变万化.比如,我们的架构师昨天说: " ...
- lua保存table到文件并从文件解析成table
require("json") result = { ["ip"]="192.168.0.177", ["date"]= ...
- datable转xml
/// <summary> /// datatable转换xml /// </summary> /// <param name="xmlDS"> ...
- 详解Ajax请求(二)——异步请求原理的分析
在上一文章里,我们分析了同步请求的原理.当浏览器向服务器发送同步请求时,服务处理同步请求的过程中,浏览器会处于等待的状态,服务器处理完请求把数据响应给浏览器并覆盖浏览器内存中原有的数据,浏览器重新加载 ...
- VMware虚拟机安装
学习Linux系统最好的方式就是在自己的虚拟机上安装Linux:接下来就给大家简单介绍一下VMware虚拟机的安装以及Linux的安装:VMware虚拟机只是为了更好的学习Linux: ...
- Vue框架axios请求(类似于ajax请求)
Vue框架axios get请求(类似于ajax请求) 首先介绍下,这个axios请求最明显的地方,通过这个请求进行提交的时候页面不会刷新 <!DOCTYPE html> <html ...
- python Mysql 库表
Mysql 库表 创建 学生信息库表 学生成绩 库表