Description

傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了。

在打仗之前,幽香现在面临一个非常基本的管理问题需要解决。 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来。

在游戏中,幽香可能在空地上增加或者减少一些军队。同时,幽香可以在一个空地上放置一个补给站。 如果补给站在点u上,并且空地v上有dv个单位的军队,那么幽香每天就要花费dvdist(u,v)的金钱来补给这些军队。

由于幽香需要补给所有的军队,因此幽香总共就要花费为Sigma(Dv
dist(u,v),其中1<=V<=N)的代价。其中dist(u,v)表示u个v在树上的距离(唯一路径的权和)。

因为游戏的规定,幽香只能选择一个空地作为补给站。在游戏的过程中,幽香可能会在某些空地上制造一些军队,也可能会减少某些空地上的军队,进行了这样的操作以后,出于经济上的考虑,幽香往往可以移动他的补给站从而省一些钱。

但是由于这个游戏的地图是在太大了,幽香无法轻易的进行最优的安排,你能帮帮她吗? 你可以假定一开始所有空地上都没有军队。

Solution

正解:动态点分

基于本题性质:度数不超过20,否则不能这么做

问题是要求一个带权重心,我们可以移动重心找到最小的一个,关键在于计算贡献是 \(O(n)\) 的.

建立重心树,我们可以\(logn\)的算出建立在当前点的代价

设 \(dis[x]\) 表示x所在的块到x的距离\(dis*dv\)之和,\(disf[x]\)表示x所在的块到x的重心树上的父亲距离\(L*dv\)的距离之和,\(w[x]\) 为x块内的\(dv\)之和

那么遍历父亲就可以算出代价了,考虑两个块贡献合并:u为计算的点,设x为儿子,v为父亲,合并的贡献为:\(dis[v]+(val[v]-val[x])*L(v,u)-disf[x]\)

意思是不含\(x\)的块到\(v\)的点的距离之和,加上不含\(x\)所在块的部分到 \(u\) 的距离

重心的移动就是判断某个儿子是否是最优的,如果是,就进入这一个块中.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
int head[N],nxt[N<<2],to[N<<2],num=0,c[N<<2],n,m,Head[N];
inline void link(int x,int y,int z){
nxt[++num]=head[x];to[num]=y;c[num]=z;head[x]=num;}
namespace tr{
int dep[N],sz[N],son[N],fa[N],top[N],dis[N];
inline void dfs1(int x){
sz[x]=1;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];if(dep[u])continue;
dep[u]=dep[x]+1;dis[u]=dis[x]+c[i];fa[u]=x;dfs1(u);
sz[x]+=sz[u];if(sz[u]>sz[son[x]])son[x]=u;
}
}
inline void dfs2(int x,int tp){
top[x]=tp;
if(son[x])dfs2(son[x],tp);
for(int i=head[x];i;i=nxt[i])
if(to[i]!=fa[x] && to[i]!=son[x])dfs2(to[i],to[i]);
}
inline int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}return dep[x]<dep[y]?x:y;
}
inline int getdis(int x,int y){return dis[x]+dis[y]-(dis[lca(x,y)]<<1);}
void main(){dep[1]=1;dfs1(1);dfs2(1,1);}
}
int rt=0,sz[N],son[N]={N},sum,S,fa[N];bool vis[N];
inline void link2(int x,int y,int v){
nxt[++num]=Head[x];to[num]=y;Head[x]=num;c[num]=v;}
inline void getroot(int x,int last){
sz[x]=1;son[x]=0;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(u==last || vis[u])continue;
getroot(u,x);sz[x]+=sz[u];
son[x]=max(son[x],sz[u]);
}
son[x]=max(son[x],sum-sz[x]);
if(son[x]<son[rt])rt=x;
}
inline void solve(int x){
vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];if(vis[u])continue;
rt=0;sum=sz[u];getroot(u,x);link2(x,rt,to[i]);fa[rt]=x;
solve(rt);
}
}
ll val[N],dis[N],disf[N];
inline void Modify(int x,int y){
for(int v=x;v;v=fa[v]){
val[v]+=y;
dis[v]+=1ll*y*tr::getdis(x,v);
if(fa[v])disf[v]+=1ll*y*tr::getdis(x,fa[v]);
}
}
inline ll ask(int x){
ll ret=dis[x];int v=x;
while(fa[v]){
ret+=dis[fa[v]]+(val[fa[v]]-val[v])*tr::getdis(fa[v],x)-disf[v];
v=fa[v];
}
return ret;
}
inline ll qry(int x){
ll ret=ask(x);
for(int i=Head[x];i;i=nxt[i])
if(ask(c[i])<ret)return qry(to[i]);
return ret;
}
void work()
{
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
link(x,y,z);link(y,x,z);
}
tr::main();
sum=n;rt=0;getroot(1,1);solve(S=rt);
while(m--){
scanf("%d%d",&x,&y);
Modify(x,y);
printf("%lld\n",qry(S));
}
}
int main()
{
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
work();
return 0;
}

bzoj 3924: [Zjoi2015]幻想乡战略游戏的更多相关文章

  1. bzoj 3924 [Zjoi2015]幻想乡战略游戏——动态点分治(暴力移动找重心)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 度数只有20,所以从一个点暴力枚举其出边,就能知道往哪个方向走. 知道方向之后直接走到 ...

  2. BZOJ 3924 ZJOI2015 幻想乡战略游戏 树链剖分

    题目链接:https://www.luogu.org/problemnew/show/P3345(bzoj权限题) 题意概述:动态维护树的上所有点到这棵树的带权重心的距离和.N,Q<=10000 ...

  3. BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)

    这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这 ...

  4. bzoj3924 [Zjoi2015]幻想乡战略游戏 点分树,动态点分

    [BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...

  5. 洛谷 P3345 [ZJOI2015]幻想乡战略游戏 解题报告

    P3345 [ZJOI2015]幻想乡战略游戏 题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做 ...

  6. [ZJOI2015]幻想乡战略游戏——动态点分治

    [ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...

  7. BZOJ3924 ZJOI2015 幻想乡战略游戏 【动态点分治】

    BZOJ3924 ZJOI2015 幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂 ...

  8. AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345

    [ZJOI2015]幻想乡战略游戏 思路: 树剖暴力转移: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...

  9. 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治

    [BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...

随机推荐

  1. django 连接mysql

    环境 Linux 修改工程目录下的settings.py 文件 #!!!!!!!!切勿出现中文 即便//注释也不行 DATABASES = { 'default': { 'ENGINE': 'djan ...

  2. hdu 3642 Get The Treasury

    Get The Treasury http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Othe ...

  3. 09-移动端开发教程-Sass入门

    1. 引言 CSS3之前的CSS都大都是枚举属性样式,而编程语言强大的变量.函数.循环.分支等功能基本都不能在CSS中使用,让CSS的编程黯淡无光,Sass就是一种增强CSS编程的扩展语言(CSS4也 ...

  4. vue初尝试--新建项目

    这是一篇技术贴--如何新建一个基于vue的项目 1.下载对应版本的nodejs安装,下载的nodejs都集成了npm,所以nodejs安装完成之后npm也对应安装完成了. 安装完成之后可以在cmd命令 ...

  5. JAVA_SE基础——21.二维数组的定义

    2 二维数组的定义 基本与一维数组类似 //定义一个3行5列的二维数组 //方法1,先new对象,然后再初始化每个元素 int[][] a = new int[3][5]; a[0][0]=1; a[ ...

  6. python安装及写一个简单的验证码组件(配合node)

    1.安装Python 到官网下载响应系统的版本(这里以windows为例):https://www.python.org/downloads/windows/ 然后就是不断地"下一步&quo ...

  7. PHP常用函数集合

    PHP常用函数总结 数学函数 1.abs(): 求绝对值 $abs = abs(-4.2); //4.2 数字绝对值数字 2.ceil(): 进一法取整 echo ceil(9.999); // 10 ...

  8. GIT入门笔记(1)- Git的基本概念

    一.概念和定义 1.git是什么 许多人习惯用复制整个项目目录的方式来保存不同的项目版本,或许还会改名加上备份时间以示区别.这么做唯一的好处就是简单.不过坏处也不少:有时候会混淆所在的工作目录,一旦弄 ...

  9. Python模块 - os , sys.shutil

    os 模块是与操作系统交互的一个接口 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录: ...

  10. 记录安装centos6.5的几个要紧步骤

    1.安装新系统 因为是服务器,不是普通电脑,貌似对usb支持不好,所以用的光盘安装. centos 6.5 64位 2.跳过测试 3.服务器语言 选择english,键盘是english.US 4.选 ...