Luogu

题意:

动态维护带权重心。

sol

这是一道写起来很舒服的动态点分治。(不像某些毒瘤题)

我们考虑,如果你选择的补给点不是当前的带权重心,那么带权重心就在补给点的一个子树中(你把补给点当做根的话)。那么,你把补给点向带权重心所在的子树中移动的时候,答案一定会减小。换言之,如果补给点无论向哪个方向移动答案都不会减小,那么这个点就是带权重心。

所以我们每次考虑移动补给点然后计算即可。

但是怎么移动呢?

最优复杂度的移动策略是:先假设点分树的根就是补给,然后你一次检查与它在原树中相连的所有点,如果有一个比它小(这样的点至多有一个),这时候你不是直接跳向这个点,而是跳向点分树中的那个儿子。这样在保证了解的范围的同时也保证了复杂度,因为点分树的树高是\(\log n\),所以最多向下跳\(\log n\)

次。

主题思想解决了,现在我们考虑怎么快速计算出以某一个点为补给点时的答案。

我们记一下三个变量(不要吐槽变量名):

\(sum_i\):表示点分树中以i为根的子树的权值和

\(gather_i\):表示点分树中以i为根的子树全部集合到i的总耗费

\(tofa_i\)表示点分树中以i为根的子树全部集合到i在点分树中的父节点的总耗费

可以发现其实\(gather_u=\sum tofa_v\),其中v是u在点分树中的儿子。之所以这样记是为了去除重复计算。

具体怎么算请自行YY。(YY有益身心健康)

总的算起来复杂度是\(O(n\log^3n)\)(但显然不满的),如果你写\(RMQLCA\)的话就是\(O(n\log^2n)\)

code

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int N = 100005;
  5. #define ll long long
  6. int gi()
  7. {
  8. int x=0,w=1;char ch=getchar();
  9. while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  10. if (ch=='-') w=0,ch=getchar();
  11. while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
  12. return w?x:-x;
  13. }
  14. int n,m,dis[N],sum[N];
  15. ll gather[N],tofa[N];
  16. struct edge{int to,next,w;}a[N<<1];
  17. int head[N],cnt,pa[N],dep[N],sz[N],son[N],top[N];
  18. void dfs1(int u,int f)
  19. {
  20. pa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
  21. for (int e=head[u];e;e=a[e].next)
  22. {
  23. int v=a[e].to;if (v==f) continue;
  24. dis[v]=dis[u]+a[e].w;dfs1(v,u);
  25. sz[u]+=sz[v];if (sz[v]>sz[son[u]]) son[u]=v;
  26. }
  27. }
  28. void dfs2(int u,int up)
  29. {
  30. top[u]=up;
  31. if (son[u]) dfs2(son[u],up);
  32. for (int e=head[u];e;e=a[e].next)
  33. if (a[e].to!=pa[u]&&a[e].to!=son[u])
  34. dfs2(a[e].to,a[e].to);
  35. }
  36. int lca(int u,int v)
  37. {
  38. while (top[u]^top[v])
  39. {
  40. if (dep[top[u]]<dep[top[v]]) swap(u,v);
  41. u=pa[top[u]];
  42. }
  43. return dep[u]<dep[v]?u:v;
  44. }
  45. int getdis(int u,int v){return dis[u]+dis[v]-2*dis[lca(u,v)];}
  46. struct node{int to,next,rt;}G[N];
  47. int vis[N],w[N],fa[N],root,tot,RT,ft[N];
  48. void getroot(int u,int f)
  49. {
  50. sz[u]=1;w[u]=0;
  51. for (int e=head[u];e;e=a[e].next)
  52. {
  53. int v=a[e].to;if (v==f||vis[v]) continue;
  54. getroot(v,u);
  55. sz[u]+=sz[v];w[u]=max(w[u],sz[v]);
  56. }
  57. w[u]=max(w[u],tot-sz[u]);
  58. if (w[u]<w[root]) root=u;
  59. }
  60. void solve(int u,int f)
  61. {
  62. fa[u]=f;vis[u]=1;int pre_tot=tot;
  63. for (int e=head[u];e;e=a[e].next)
  64. {
  65. int v=a[e].to;if (vis[v]) continue;
  66. if (sz[v]>sz[u]) tot=pre_tot-sz[u];
  67. else tot=sz[v];
  68. root=0;
  69. getroot(v,0);
  70. G[++cnt]=(node){v,ft[u],root};ft[u]=cnt;
  71. solve(root,u);
  72. }
  73. }
  74. void Modify(int u,int val)
  75. {
  76. sum[u]+=val;
  77. for (int i=u;fa[i];i=fa[i])
  78. {
  79. int dist=getdis(u,fa[i]);
  80. sum[fa[i]]+=val;
  81. gather[fa[i]]+=(ll)val*dist;
  82. tofa[i]+=(ll)val*dist;
  83. }
  84. }
  85. ll calc(int u)
  86. {
  87. ll res=gather[u];
  88. for (int i=u;fa[i];i=fa[i])
  89. {
  90. int dist=getdis(u,fa[i]);
  91. res+=(ll)(sum[fa[i]]-sum[i])*dist;
  92. res+=gather[fa[i]]-tofa[i];
  93. }
  94. return res;
  95. }
  96. ll Query(int u)
  97. {
  98. ll temp=calc(u);
  99. for (int e=ft[u];e;e=G[e].next)
  100. if (calc(G[e].to)<temp) return Query(G[e].rt);
  101. return temp;
  102. }
  103. int main()
  104. {
  105. n=gi();m=gi();
  106. for (int i=1;i<n;i++)
  107. {
  108. int u=gi(),v=gi(),w=gi();
  109. a[++cnt]=(edge){v,head[u],w};head[u]=cnt;
  110. a[++cnt]=(edge){u,head[v],w};head[v]=cnt;
  111. }
  112. dfs1(1,0);dfs2(1,1);
  113. w[0]=tot=n;cnt=0;
  114. getroot(1,0);
  115. RT=root;
  116. solve(root,0);
  117. while (m--)
  118. {
  119. int u=gi(),e=gi();
  120. Modify(u,e);
  121. printf("%lld\n",Query(RT));
  122. }
  123. return 0;
  124. }

[Luogu3345][ZJOI2015]幻想乡战略游戏的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. [ZJOI2015]幻想乡战略游戏

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

  9. bzoj 3924: [Zjoi2015]幻想乡战略游戏

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

随机推荐

  1. [Python Study Notes]匿名函数

    Python 使用 lambda 来创建匿名函数. lambda这个名称来自于LISP,而LISP则是从lambda calculus(一种符号逻辑形式)取这个名称的.在Python中,lambda作 ...

  2. centos出现“FirewallD is not running”怎么办

    最近在阿里云服务器centos上安装了mysql数据库,默认是不开启远端访问功能,需要设置一下防火墙,在开放默认端口号 3306时提示FirewallD is not running,经过排查发现是防 ...

  3. LINUX下的U盘挂载

    linux下如果没有图形界面的情况下就要我们自己熟悉命令来挂载U盘,下面给大家详细描述下U盘的挂载过程. 1. 插入U盘 2. #sudo fdisk –l 查看所挂载盘符名称如下图,假设盘符名称为s ...

  4. PHP两个日期之间的所有日期

    我想得到两个日期之间的所有日期, 例如:输入两个日期,把这两个日期之间的所有日期取出来     如果是:2005-02-01至2005-02-05(同为一个月)     则为:2005-02-01,2 ...

  5. CentOS 挂载 cdrom, iso文件作为源

    在生产系统环境中的机器都没有连接互联网,因此都是使用本地源. 首先,需要将cdrom, 或 iso文件挂载到本地目录. 1.挂载光驱: 将cdrom 放入光驱. $  mkdir /media/cdr ...

  6. 10分钟入门kubernetes(上)

    kubernetes简称k8s, 主要用途是automate deployment, scaling, and managment of containerized applications.是目前非 ...

  7. Java经典编程题50道之三十五

    有一个数组,将其最大的元素与第一个元素交换,最小的元素与最后一个元素交换,然后输出数组. public class Example35 {    public static void main(Str ...

  8. Yii2整合AdminLTE后台主题

    首先你要确保你已经安装好了Yii2 advanced高级模板,并且跑的通. 安装AdminLTE其实没有网上说的那么简单,网上千篇一律的推荐Composer安装,虽然Composer很方便,但是在中国 ...

  9. 如何使用supervisor管理你的应用

    1.前言 Supervisor(http://supervisord.org/)是用Python开发的一个client/server服务,是UNIX-like系统下的一个进程管理工具,不支持Windo ...

  10. spring cloud熔断监控Hystrix Dashboard和Turbine

    参考: http://blog.csdn.net/ityouknow/article/details/72625646 完整pom <?xml version="1.0" e ...