【BZOJ3924】[Zjoi2015]幻想乡战略游戏

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

第一行两个数n和Q分别表示树的点数和幽香操作的个数,其中点从1到n标号。 
接下来n-1行,每行三个正整数a,b,c,表示a和b之间有一条边权为c的边。 
接下来Q行,每行两个数u,e,表示幽香在点u上放了e单位个军队
(如果e<0,就相当于是幽香在u上减少了|e|单位个军队,说白了就是du←du+e)。
数据保证任何时刻每个点上的军队数量都是非负的。 
1<=c<=1000, 0<=|e|<=1000, n<=10^5, Q<=10^5
对于所有数据,这个树上所有点的度数都不超过20
N,Q>=1

Output

对于幽香的每个操作,输出操作完成以后,每天的最小花费,也即如果幽香选择最优的补给点进行补给时的花费。

Sample Input

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

Sample Output

0
1
4
5
6

题意:给你一棵树,多次改变一个点的权值或询问所有点到当前带权重心的带权距离是多少。

题解:先考虑如何求所有点到一个点的带权距离。我们先沿用树形DP的思想,令:

s1:每个点的子树中的所有点到该点的带权距离。
s2:每个点的子树中的所有点到该点的父亲的带权距离。
s3:每个点的子树中的所有点的权值和。

然后就可以统计答案了,从每个点一直向上爬,沿途记录所有点的s1,减去重复的部分的s2,再加上不足的距离dis*s3,细节还是自己搞吧~时间复杂度logn。

由于题目保证每个点的度数<=20,那么我们可以采用如下方法找重心:从分治结构的root开始,枚举它的所有出边(原树中的出边),如果往那个方向走得到的总距离比当前的优,则走到那条出边对应的(分治结构中的)儿子上,否则当前点就是重心。总复杂度O(nlog2n*20)。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,m,tot,rt,root,mn,cnt;
int to[maxn<<1],next[maxn<<1],head[maxn],siz[maxn],fa[maxn],vis[maxn];
int pos[maxn],Log[maxn<<1];
ll md[19][maxn<<1],dep[maxn],val[maxn<<1];
ll s1[maxn],s2[maxn],s3[maxn]; //s1:点*边,s2:点,s3到父亲的
vector<int> c1[maxn],c2[maxn];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x,int fa)
{
md[0][++pos[0]]=dep[x],pos[x]=pos[0];
for(int i=head[x];i!=-1;i=next[i])
if(to[i]!=fa) dep[to[i]]=dep[x]+val[i],dfs(to[i],x),md[0][++pos[0]]=dep[x];
}
void getrt(int x,int fa)
{
siz[x]=1;
int i,tmp=0;
for(i=head[x];i!=-1;i=next[i])
if(!vis[to[i]]&&to[i]!=fa)
getrt(to[i],x),siz[x]+=siz[to[i]],tmp=max(tmp,siz[to[i]]);
tmp=max(tmp,tot-siz[x]);
if(tmp<mn) mn=tmp,rt=x;
}
void solve(int x)
{
vis[x]=1;
for(int i=head[x];i!=-1;i=next[i])
if(!vis[to[i]])
tot=siz[to[i]],mn=1<<30,getrt(to[i],x),fa[rt]=x,c1[x].push_back(rt),c2[x].push_back(to[i]),solve(rt);
}
ll lca(int a,int b)
{
a=pos[a],b=pos[b];
if(a>b) swap(a,b);
int k=Log[b-a+1];
return min(md[k][a],md[k][b-(1<<k)+1]);
}
ll dis(int a,int b)
{
return dep[a]+dep[b]-2*lca(a,b);
}
void updata(int x,int y,ll z)
{
s1[x]+=dis(x,y)*z,s2[x]+=z;
if(!fa[x]) return ;
s3[x]+=dis(fa[x],y)*z;
updata(fa[x],y,z);
}
ll getdis(int x,int y)
{
ll ret=s1[x];
if(fa[x]) ret+=getdis(fa[x],y)-s3[x]+(s2[fa[x]]-s2[x])*dis(fa[x],y);
return ret;
}
int moveroot(int x)
{
ll now=getdis(x,x);
for(int i=0,j=0;i<(int)c1[x].size();i++,j++) if(getdis(c2[x][i],c2[x][i])<now)
return moveroot(c1[x][j]);
return x;
}
int main()
{
n=rd(),m=rd();
int i,j,a,b,c;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
dep[1]=1,dfs(1,0);
for(i=2;i<=2*n-1;i++) Log[i]=Log[i>>1]+1;
for(j=1;(1<<j)<=2*n-1;j++) for(i=1;i+(1<<j)-1<=2*n-1;i++)
md[j][i]=min(md[j-1][i],md[j-1][i+(1<<(j-1))]);
tot=n,mn=1<<30,getrt(1,0),root=rt,solve(rt);
for(i=1;i<=m;i++)
{
a=rd(),b=rd();
updata(a,a,b);
rt=moveroot(root);
printf("%lld\n",getdis(rt,rt));
}
return 0;
}//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

【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治的更多相关文章

  1. [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)

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

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

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

  3. 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治

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

  4. ZJOI2015 幻想乡战略游戏 动态点分治_树链剖分_未调完

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

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

    \(\color{#0066ff}{ 题目描述 }\) 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越 ...

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

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

  7. BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)

    题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑​dist(x,i)∗a[i]的最 ...

  8. 洛谷P3345 [ZJOI2015]幻想乡战略游戏 [动态点分治]

    传送门 调了两个小时,终于过了-- 凭啥人家代码80行我180行啊!!! 谁叫你大括号换行 谁叫你写缺省源 思路 显然,补给点所在的位置就是这棵树的带权重心. 考虑size已知时如何找重心:一开始设答 ...

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

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

随机推荐

  1. Spark-RDD之 zip

    zip这个函数是在scala中的,spark中也应用于RDD类型 val posLeftRDD = FreqDic1.map(line => line._1) zip sc.paralleliz ...

  2. iOS 5 does not allow to store downloaded data in Documents directory? ios5.0及以后的版本对于下载的文件存储路径有了改变

    I have made an application for my client by keeping target iOS as 4. But since the application still ...

  3. How To Commit Just One Data Block Changes In Oracle Forms

    You have an Oracle Form in which you have multiple data blocks and requirement is to commit just one ...

  4. C语言对文件的读写操作以及处理CSV文件的方法

    #include <stdio.h> #define F_PATH "d:\myfile\file.txt" int main(void) { FILE *fp = N ...

  5. AlphaGo GITHUB

    AlphaGo GITHUB https://github.com/Rochester-NRT/AlphaGo

  6. GLSL纹理贴图 【转】

    转载:http://blog.csdn.net/hgl868/article/details/7872466 简单的纹理贴图(Simple Texture) 为了在GLSL中应用纹理,我们需要访问每个 ...

  7. 左手系,右手系,row major, column major

    http://www.cnblogs.com/minggoddess/p/3672863.html dx 左手系 row major ogl 右手系 column major 差了个 matrix   ...

  8. Linux学习之十-Linux系统时间

    Linux系统时间 1.date命令用于查看以及修改Linux系统的时间,关于date命令的详细帮助文档如下 [root@localhost ~]# date --help Usage: date [ ...

  9. 2017.2.21 activiti实战--第十三章--流量数据查询与跟踪(一)查询接口介绍及运行时数据查询

    学习资料:<Activiti实战> 第十三章 流量数据查询与跟踪 本章讲解运行时与历史数据的查询方法.主要包含三种:标准查询,Native查询,CustomSql查询. 13.1 Quer ...

  10. script脚本中写不写$(document).ready(function() {});的差别

    $(document).ready() 里的代码是在页面内容都载入完才运行的,假设把代码直接写到script标签里.当页面载入完这个script标签就会运行里边的代码了,此时假设你标签里运行的代码调用 ...