【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:每个点的子树中的所有点的权值和。

可以先计算出每个重心的S

那S -- T 会改变什么

Δ=T-S=(∑valu->S-∑valv->T)*e.v,发现随着移动,属于S的会更多,不会少,所有

发现这个函数是一定会从负到正,到正以后没有意义了,因为答案是需要最小

所以就这样了。

这道题目在当时省选的时候是不可以暴力转移根的,但也有一些分数,

bzoj上是直接可以过的,

但是这里该怎么办呢,就需要建立点分树。

点分树上是log的,所以在点分树上跳就只需要log次,所以复杂度就有了保证。

 #include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector> #define ll long long
#define N 100007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if (ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,tot,rt,root,mn;
int cnt,hed[N],nxt[N*],rea[N*];
int pos[N],Log[N*],fa[N],vis[N],siz[N];
ll md[][N*],dep[N],val[N*];
ll s1[N],s2[N],s3[N];
vector<int>c1[N],c2[N]; void add(int u,int v,int w)
{
nxt[++cnt]=hed[u];
hed[u]=cnt;
rea[cnt]=v;
val[cnt]=w;
}
void dfs(int u,int fa)
{
md[][++pos[]]=dep[u],pos[u]=pos[];
for(int i=hed[u];i!=-;i=nxt[i])
{
int v=rea[i];
if (v==fa)continue;
dep[v]=dep[u]+val[i],dfs(v,u),md[][++pos[]]=dep[u];
}
}
void get_root(int u,int fa)
{
siz[u]=;
int res=;
for (int i=hed[u];i!=-;i=nxt[i])
{
int v=rea[i];
if (v==fa||vis[v])continue;
get_root(v,u);
siz[u]+=siz[v],res=max(res,siz[v]);
}
res=max(res,tot-siz[u]);
if (res<mn) mn=res,rt=u;
}
void solve(int u)
{
vis[u]=;
for (int i=hed[u];i!=-;i=nxt[i])
{
int v=rea[i];
if (vis[v])continue;
tot=siz[v],mn=<<;
get_root(v,u),fa[rt]=u;
c1[u].push_back(rt);
c2[u].push_back(v);
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+];
return min(md[k][a],md[k][b-(<<k)+]);
}
ll dis(int a,int b)
{
return dep[a]+dep[b]-*lca(a,b);
}
void modify(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;
modify(fa[x],y,z);
}
ll get_dis(int x,int y)
{
ll res=s1[x];
if (fa[x])res+=get_dis(fa[x],y)-s3[x]+(s2[fa[x]]-s2[x])*dis(fa[x],y);
return res;
}
int goto_root(int u)
{
ll now=get_dis(u,u);
for (int i=,j=;i<(int)c1[u].size();i++,j++)
if (get_dis(c2[u][i],c2[u][i])<now)return goto_root(c1[u][j]);
return u;
}
int main()
{
memset(hed,-,sizeof(hed));
n=read(),m=read();
for (int i=;i<n;i++)
{
int x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
dep[]=,dfs(,);
for (int i=;i<=*n-;i++)
Log[i]=Log[i>>]+;
for (int i=;(<<i)<=(*n-);i++)
for (int j=;j+(<<i)-<=*n-;j++)
md[i][j]=min(md[i-][j],md[i-][j+(<<(i-))]);
tot=n,mn=<<;
get_root(,),root=rt,solve(rt);
for (int i=;i<=m;i++)
{
int x=read(),y=read();
modify(x,x,y);
rt=goto_root(root);//每次从原树中继续分治。
//cout<<"rt="<<rt<<endl;
printf("%lld\n",get_dis(rt,rt));
}
}

bzoj3924 [Zjoi2015]幻想乡战略游戏 点分树,动态点分的更多相关文章

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

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

  2. BZOJ3924 [Zjoi2015]幻想乡战略游戏

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

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

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

  4. BZOJ3924——[Zjoi2015]幻想乡战略游戏

    0.题意:动态维护带权中心 1.分析:妈的,这题做了一天,mdzzzzzzzzzzzzzzzzzz-.. 这个题是边权,我们首先要将边权转化成点权... 我们维护一个分支结构中到根的距离和,一个分支结 ...

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

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

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

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

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

    [BZOJ3924]幻想乡战略游戏(动态点分治) 题面 权限题...(穷死我了) 洛谷 题解 考虑不修改 发现一个贪心的做法 假设当前放在当前位置 如果它有一个子树的兵的总数大于总数的一半 那么,放到 ...

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

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

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

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

随机推荐

  1. falling object思路总结

    1.用检测的方法把falling object标记为一个类别,然后检测出类别.这种方式不可行的原因:因为falling object可能是任何东西,所以可能是一个路锥,也可能是一个玻璃瓶,还可能是掉下 ...

  2. ubuntu18.04 安装五笔拼音

    sudo apt install fcitx-table-wubi fcitx-table-wbpy 在输入法中加入五笔拼音就可以了,如果原来使用的是ibus, 改为fcitx后,重启机器.

  3. Python——函数的高级应用

    一.函数赋值给变量 函数也是对象,也可以赋值给变量,当把函数赋值给变量后,可以通过变量调用函数. 例: def test(x,y): return x * y # 把函数赋值给变量 a = test ...

  4. Python——print用法详解

    1.print语法格式 print()函数具有丰富的功能,详细语法格式如下:print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=Fa ...

  5. Golang Json测试

    结构体是谷歌搜索API package main import ( "encoding/json" "fmt" "io/ioutil" &q ...

  6. 用宝塔软件在linux上自动安装php环境

    1.确保是纯净系统 确保是干净的操作系统,没有安装过其它环境带的Apache/Nginx/php/MySQL,否则安装不上 2.sudo进行安装 yum install -y wget &&a ...

  7. asp发送短信验证码 pst方式

    <script language="jscript" runat="server">  Array.prototype.get = function ...

  8. python向上取整 向下取整

    向上取整 ceil() 函数返回数字的向上取整整数,就是返回大于等于变量的最近的整数. ceil()是不能直接访问的,需要导入 math 模块. import math math.ceil( x ) ...

  9. Python 中的for,if-else和while语句

    for 循环 功能 for 循环是一种迭代循环机制,迭代即重复相同的逻辑操作,每次的操作都是基于上一次的结果而进行的.并且for循环可以遍历任何序列的项目,如一个列表或者一个字符串 语法 for 循环 ...

  10. leetcode-20-Dynamic Programming

    303. Range Sum Query - Immutable 解题思路: Note里说sumRange会被调用很多次..所以简直强烈暗示要做cache啊...所以刚开始,虽然用每次都去遍历数组求和 ...