题意自己看。。。

思路

没想到今(昨)天刷着刷着点分治的水题,就刷出来了一个点分树。。。

然后就疯狂地找题解,代码,最后终于把它给弄懂了。

点分树——动态点分治,对于此题来说,我们设u为当前的补给站位置,v是它的一个儿子。同时设dis(i,j)为树上i点到j点的距离。cnti为以i为根的子树中d(也就是军队数)的总量

我们把补给站从u转移到v(假设u是树的根),答案的变化为dis(u,v)*(cntu-cntv)-dis(u,v)*cntv=dis(u,v)*(cntu-2*cntv)

所以当2*cntv>cntu把补给站转移v会使答案变优,一直这样操作下去,直到不管如何转移都无法使答案变优,当前点就是答案。

我们对于每一次修改都维护一下然后默认当前点为补给站且为当前树的根,然后像刚才一样转移补给站,就有了这个题的大体思路。

但这样肯定会爆炸啊(每次只会转移一步,复杂度和深度有关)

所以我们就可以用到点分树了。

我们利用点分治的方法(找重心作为根节点,然后递归处理子树)重新构建一颗树,称为分治树。

举个例子,比如说样例

(左为原树右为分治树)

这样我们就得到一颗深度为log的树。

这样我们转移就不会因为深度太大而GG了。

但是,这样一来的话因为树的结构不一样了,补给站的转移就会很难。因为一个点在分治树的儿子在原树中不一定和它直接相连

(之后我们的补给站的转移都是在分治树上进行的)

但还是有办法解决的。我们记录这这些东西。dis(i,j)为i,j在原树的距离。cnt[i]为分治树中以i为根的子树中有多少个d,sumi为分治树中以i为根的子树中所有的点j的dis(i,j)*dj之和,sumch(i,j)记录i点第j个儿子的sum。

我们现在讨论从u转移到它分治树中的一个子节点v,v是原来这颗子树中的重心但在原树中并不一定和u之间相连,我们设原树中直接和u相连的点是w。

因为把补给站转到v的时候要把v作为整棵树的根,只要把v所在子树之外的所有信息扔到w中然后递归就可以了。那怎么维护w的信息呢?

我们记录在v处记录下w和w与u这条边的权值c,然后我们在cntw处加上cnt[u]-cnt[v],然后在sumw处加上sum[u]-sumch(i,v)+(cnt[u]-cnt[v])*c;

最后答案就取sum[当前点]就行了。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define int long long
const int N=1e5+;
struct son{int v,rv,w;};
struct node{int u,c,w;};
struct pre{int to,w;};
vector<son>ch[N];
vector<node>stack;
vector<pre>f[N];
vector<int>sumch[N];
int num,head[N];
int g[N],root,size[N],all,vis[N];
int realroot,sum[N],cnt[N],n,m;
struct edge{
int to,nxt,w;
}e[N*];
void add_edge(int u,int v,int w){
num++;
e[num].nxt=head[u];
e[num].to=v;
e[num].w=w;
head[u]=num;
}
int read(){
int sum=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){sum=sum*+ch-'';ch=getchar();}
return sum*f;
}
void getroot(int u,int f){
g[u]=;size[u]=;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f||vis[v])continue;
getroot(v,u);
g[u]=max(g[u],size[v]);
size[u]+=size[v];
}
g[u]=max(g[u],all-size[u]);
if(g[u]<g[root])root=u;
}
void dfs(int u,int fa,int top,int w){
pre x;x.to=top;x.w=w;
f[u].push_back(x);
size[u]=;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]||v==fa)continue;
dfs(v,u,top,w+e[i].w);
size[u]+=size[v];
}
}
void work(int u){
pre y;y.w=;y.to=u;
f[u].push_back(y);
vis[u]=;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]==)continue;
dfs(v,,u,e[i].w);
root=,all=size[v];
getroot(v,);
son x;x.v=root;x.rv=v;x.w=e[i].w;
ch[u].push_back(x);
work(root);
}
}
void update(int u,int c,int w){
for(int i=;i<f[u].size();i++){
int v=f[u][i].to;
int L=f[u][i].w;
cnt[v]+=c;
sum[v]+=w+c*L;
if(i!=f[u].size()-)
for(int j=;j<ch[v].size();j++){
if(ch[v][j].v==f[u][i+].to)sumch[v][j]+=w+c*L;
}
}
}
int check(){
int now=realroot,mx;
stack.clear();
while(now){
mx=;
for(int i=;i<ch[now].size();i++)
if(cnt[ch[now][i].v]>cnt[ch[now][mx].v])mx=i;
if(ch[now].size()==||cnt[ch[now][mx].v]*<=cnt[now]){
int ans=sum[now];
for(int i=;i<stack.size();i++)
update(stack[i].u,stack[i].c,stack[i].w);
return ans;
}
int v=ch[now][mx].v;
node x;
x.u=ch[now][mx].rv;x.c=-(cnt[now]-cnt[v]);
x.w=-(sum[now]-sumch[now][mx]+(cnt[now]-cnt[v])*ch[now][mx].w);
stack.push_back(x);
update(x.u,-x.c,-x.w);
now=v;
}
}
signed main(){
n=read();m=read();
for(int i=;i<n;i++){
int u=read(),v=read(),w=read();
add_edge(u,v,w);add_edge(v,u,w);
}
g[]=n+;root=;all=n;
getroot(,);realroot=root;
work(root);
for(int i=;i<=n;i++)sumch[i]=vector<int>(ch[i].size(),);
while(m--){
int x=read(),y=read();
update(x,y,);
printf("%lld\n",check());
}
return ;
}

[ZJOI2015]幻想乡战略游戏(点分树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. 2018.08.28 洛谷P3345 [ZJOI2015]幻想乡战略游戏(点分树)

    传送门 题目就是要求维护带权重心. 因此破题的关键点自然就是带权重心的性质. 这时发现直接找带权重心是O(n)的,考虑优化方案. 发现点分树的树高是logn级别的,并且对于以u为根的树,带权重心要么就 ...

  8. 【洛谷3345_BZOJ3924】[ZJOI2015]幻想乡战略游戏(点分树)

    大概有整整一个月没更博客了 -- 4 月为省选爆肝了一个月,最后压线进 B 队,也算给 NOIP2018 翻车到 316 分压线省一这个折磨了五个月的 debuff 画上了一个不算太差的句号.结果省选 ...

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

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

随机推荐

  1. Reflection (computer programming) -反射-自身结构信息

    n computer science, reflection is the ability of a computer program to examine, introspect, and modi ...

  2. ZBrush中Mrgb、Rgb和M的使用

    ZBrush®软件工具架中所有的命令选项都是我们平时较为常用的,位于工具架的中间位置,有一个Mrgb.Rgb和M选项它们所表示的是材质及颜色,那么,在Zbrush中只要选择相应的选项,就可以同时绘制材 ...

  3. pytorch实战(2)-----回归例子

    一.回归任务介绍: 拟合一个二元函数 y = x ^ 2. 二.步骤: 导入包 创建数据 构建网络 设置优化器和损失函数 前向和后向传播训练网络 画图 三.代码: 导入包: import torch ...

  4. [置顶] 献给写作者的 Markdown 新手指南

    作者:http://jianshu.io/p/q81RER 出处:http://jianshu.io/p/q81RER 献给写作者的 Markdown 新手指南 简书 「简书」作为一款「写作软件」在诞 ...

  5. HDU 1042 N!( 高精度乘法水 )

    链接:传送门 思路:高精度乘法板子题,高精度耗时又耗空间...... /**************************************************************** ...

  6. NOIP2013 华容道 (棋盘建图+spfa最短路)

    #include <cstdio> #include <algorithm> #include <cstring> #include <queue> # ...

  7. python3 列表操作

    - 创建列表 #创建列表: list1 = [1, 2, 3, 4, 5] - 向列表中添加元素 - append # 向列表中添加元素: list1 = [1, 2, 3, 4, 5] list1. ...

  8. ASP.NET-RedirectToAction只能使用get方法

    两个同名Action共同使用return View() return RedirectToAction("test", new { ls = list.Fct_OrderList ...

  9. oracle学习之第一个存储过程:打印Hello World

    数据库对象:表.视图.索引.序列.同义词.存储过程.存储函数 存储过程:指的是存储在数据库中供全部用户程序调用的子程序叫存储过程.存储函数 存储过程和存储函数的同样点:完毕特定功能的程序 存储过程和存 ...

  10. 安卓ProgressBar水平进度条的颜色设置

    安卓系统提供了水平进度条ProgressBar的样式,而我们在实际开发中,差点儿不可能使用默认的样式.原因就是"太丑"^_^ 所以我们在很多其它的时候须要对其颜色进行自己定义,主要 ...