[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 ...
随机推荐
- 2017-2018-1 Java演绎法 第一周 作业
团队学习:<构建之法> [团队成员]: 学号 姓名 负责工作 20162315 马军 日常统计,项目部分代码 20162316 刘诚昊 项目部分代码,代码质量测试 20162317 袁逸灏 ...
- 学号:201621123032 《Java程序设计》第8周学习总结
1:本周学习总结 2:书面作业 2.1:ArrayList代码分析 2.1.1:解释ArrayList的contains源代码 Contains方法调用indexof方法,如果元素为null,则循环比 ...
- Java基础 成员变量的继承与覆盖
通过继承可以得到父类的成员变量,子类的成员变量包括从父类继承的成员变量(包括从祖先类中继承的成员变量)以及子类中重新定义的成员变量.本次介绍内容包括:可以继承哪些成员?如果子类和父类出现了相同的成员变 ...
- 利用Python爬取新浪微博营销案例库并下载到本地
from bs4 import BeautifulSoup import requests,urllib.request,urllib.parse import json import time im ...
- webView调用系统地图,电话,和跳转链接的方法
webView.dataDetectorTypes = UIDataDetectorTypePhoneNumber | UIDataDetectorTypeLink | UIDataDetectorT ...
- nyoj 邮票分你一半
邮票分你一半 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 小珂最近收集了些邮票,他想把其中的一些给他的好朋友小明.每张邮票上都有分值,他们想把这些邮票分 ...
- python之路--day15--常用模块之logging模块
常用模块 1 logging模块 日志级别:Noset (不设置) Debug---(调试信息)----也可用10表示 Info--(消息信息)----也可用20表示 Warning---(警告信息) ...
- margin-top导致父标签偏移问题
从一个大神博客中看到这句话: 这个问题发生的原因是根据规范,一个盒子如果没有上补白(padding-top)和上边框(border-top),那么这个盒子的上边距会和其内部文档流中的第一个子元素的上边 ...
- 《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet
软件:Cisco Packet Tracer Instructor 软件下载链接在上一篇文章中. 内容:通过设置三个密码,熟悉采用Telnet方式配置交换机的方法. 细节说明:计算机的IP地址和交换机 ...
- 到底什么是 "method group"
class Program { delegate void NoParam(); delegate void WithOneParam(string name); static void Main(s ...