动态点分治

先建出点分树,每个点上维护两个堆,s1,s2,分别表示子树中到点分树中父亲的所有长度,每个儿子s1的最大值,那么对于每个点答案就是s2的最大+次大,再维护一个s3保存这个。

首先我们要搞一个带删除的堆,那么我们开两个堆就行了,一个保存元素,一个保存被删除的元素,每次一起弹出就行了

然后是为什么要维护三个堆,每个点记录所有儿子的路径不行吗》这里我想了很长时间,其实很简单,因为记录路径的话有可能最大和次大都是从一个儿子里来的。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + ;
  4. int rd()
  5. {
  6. int x = , f = ; char c = getchar();
  7. while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
  8. while(c >= '' && c <= '') { x = x * + c - ''; c = getchar(); }
  9. return x * f;
  10. }
  11. int n, sum, m, root;
  12. int size[N], f[N], vis[N], val[N], dep[N], fa[N][], Fa[N];
  13. vector<int> G[N];
  14. struct Heap {
  15. priority_queue<int> A, B;
  16. void push(int x) { A.push(x); }
  17. void del(int x) { B.push(x); }
  18. int top()
  19. {
  20. while(!A.empty() && !B.empty() && A.top() == B.top()) A.pop(), B.pop();
  21. return A.top();
  22. }
  23. int sum()
  24. {
  25. int x = top();
  26. A.pop();
  27. int y = top();
  28. A.push(x);
  29. return x + y;
  30. }
  31. int size()
  32. {
  33. return A.size() - B.size();
  34. }
  35. } s1[N], s2[N], s3;
  36. void erase(Heap &s)
  37. {
  38. if(s.size() > ) s3.del(s.sum());
  39. }
  40. void Insert(Heap &s)
  41. {
  42. if(s.size() > ) s3.push(s.sum());
  43. }
  44. void dfs(int u, int last)
  45. {
  46. for(int i = ; i < G[u].size(); ++i)
  47. {
  48. int v = G[u][i];
  49. if(v == last) continue;
  50. fa[v][] = u;
  51. dep[v] = dep[u] + ;
  52. dfs(v, u);
  53. }
  54. }
  55. int lca(int u, int v)
  56. {
  57. if(dep[u] < dep[v]) swap(u, v);
  58. int d = dep[u] - dep[v];
  59. for(int i = ; i >= ; --i)
  60. if(d & ( << i))
  61. u = fa[u][i];
  62. if(u == v) return u;
  63. for(int i = ; i >= ; --i)
  64. if(fa[u][i] != fa[v][i])
  65. u = fa[u][i],
  66. v = fa[v][i];
  67. return fa[u][];
  68. }
  69. int getsize(int u, int last)
  70. {
  71. int ret = ;
  72. for(int i = ; i < G[u].size(); ++i)
  73. {
  74. int v = G[u][i];
  75. if(v == last || vis[v]) continue;
  76. ret += getsize(v, u);
  77. }
  78. return ret;
  79. }
  80. void getroot(int u, int last, int S)
  81. {
  82. f[u] = ;
  83. size[u] = ;
  84. for(int i = ; i < G[u].size(); ++i)
  85. {
  86. int v = G[u][i];
  87. if(v == last || vis[v]) continue;
  88. getroot(v, u, S);
  89. size[u] += size[v];
  90. f[u] = max(f[u], size[v]);
  91. }
  92. f[u] = max(f[u], S - size[u]);
  93. if(f[u] < f[root]) root = u;
  94. }
  95. void divide(int u)
  96. {
  97. vis[u] = ;
  98. for(int i = ; i < G[u].size(); ++i)
  99. {
  100. int v = G[u][i];
  101. if(vis[v]) continue;
  102. root = ;
  103. getroot(v, u, getsize(v, u));
  104. Fa[root] = u;
  105. divide(root);
  106. }
  107. }
  108. int dis(int u, int v)
  109. {
  110. int x = lca(u, v);
  111. return dep[u] + dep[v] - * dep[x];
  112. }
  113. void join(int u)
  114. {
  115. int tmp = u;
  116. erase(s2[u]);
  117. s2[u].push();
  118. Insert(s2[u]);
  119. while(Fa[u])
  120. {
  121. erase(s2[Fa[u]]);
  122. if(s1[u].size()) s2[Fa[u]].del(s1[u].top());
  123. s1[u].push(dis(Fa[u], tmp));
  124. s2[Fa[u]].push(s1[u].top());
  125. Insert(s2[Fa[u]]);
  126. u = Fa[u];
  127. }
  128. }
  129. void remove(int u)
  130. {
  131. int tmp = u;
  132. erase(s2[u]);
  133. s2[u].del();
  134. Insert(s2[u]);
  135. while(Fa[u])
  136. {
  137. erase(s2[Fa[u]]);
  138. s2[Fa[u]].del(s1[u].top());
  139. s1[u].del(dis(tmp, Fa[u]));
  140. if(s1[u].size()) s2[Fa[u]].push(s1[u].top());
  141. Insert(s2[Fa[u]]);
  142. u = Fa[u];
  143. }
  144.  
  145. }
  146. int main()
  147. {
  148. f[] = 1e9;
  149. n = sum = rd();
  150. for(int i = ; i < n; ++i)
  151. {
  152. int u = rd(), v = rd();
  153. G[u].push_back(v);
  154. G[v].push_back(u);
  155. }
  156. dfs(, );
  157. for(int j = ; j <= ; ++j)
  158. for(int i = ; i <= n; ++i)
  159. fa[i][j] = fa[fa[i][j - ]][j - ];
  160. getroot(, , getsize(, ));
  161. divide(root);
  162. m = rd();
  163. for(int i = ; i <= n; ++i) join(i), val[i] = ;
  164. while(m--)
  165. {
  166. char opt[];
  167. scanf("%s", opt);
  168. if(opt[] == 'G')
  169. {
  170. if(sum < ) printf("%d\n", sum - );
  171. else printf("%d\n", s3.top());
  172. }
  173. if(opt[] == 'C')
  174. {
  175. int u = rd();
  176. if(val[u] == )
  177. {
  178. val[u] = ;
  179. remove(u);
  180. --sum;
  181. }
  182. else
  183. {
  184. val[u] = ;
  185. join(u);
  186. ++sum;
  187. }
  188. }
  189. }
  190. return ;
  191. }

bzoj1095的更多相关文章

  1. 【BZOJ1095】捉迷藏(动态点分治)

    [BZOJ1095]捉迷藏(动态点分治) 题面 BZOJ 题解 动态点分治板子题 假设,不考虑动态点分治 我们来想怎么打暴力: \(O(n)DP\)求树的最长链 一定都会.不想解释了 所以,利用上面的 ...

  2. 动态点分治:Bzoj1095: [ZJOI2007]Hide 捉迷藏

    简介 这是我自己的一点理解,可能写的不好 点分治都学过吧.. 点分治每次找重心把树重新按重心的深度重建成了一棵新的树,称为分治树 这个树最多有log层... 动态点分治:记录下每个重心的上一层重心,这 ...

  3. BZOJ1095 [ZJOI2007]Hide 捉迷藏 动态点分治 堆

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1095.html 题目传送门 - BZOJ1095 题意 有 N 个点,每一个点是黑色或者白色,一开始所 ...

  4. 【bzoj1095】 ZJOI2007—捉迷藏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1095 (题目链接) 题意 一棵树,求最远的两黑点之间的距离,每次可以将黑点染白或者将白点染黑. So ...

  5. BZOJ1095 [ZJOI2007]Hide 捉迷藏 【动态点分治 + 堆】

    题目链接 BZOJ1095 题解 传说中的动态点分治,一直不敢碰 今日一会,感觉其实并不艰涩难懂 考虑没有修改,如果不用树形dp的话,就得点分治 对于每个重心,我们会考虑其分治的子树内所有点到它的距离 ...

  6. 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆

    [BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...

  7. [bzoj1095][ZJOI2007]Hide 捉迷藏 点分树,动态点分治

    [bzoj1095][ZJOI2007]Hide 捉迷藏 2015年4月20日7,8876 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiaji ...

  8. BZOJ1095 [ZJOI2007]Hide 捉迷藏

    动态树分治,用三个set分别维护每个重心到每一个子树的距离种类.每个重心所有子树的最大值和次大值.全局答案的最大值.复杂度O(nlogn^2) 代码 #include<cstdio> #i ...

  9. bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治

    这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...

  10. 【BZOJ1095】 Hide 捉迷藏

    Time Limit: 4000 ms   Memory Limit: 256 MB Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.W ...

随机推荐

  1. Unable to satisfy the following requirements解决方式

    今天从git上面download我们项目,然后向往常一样安装Cocoapods.可是却突然发现报错了,尝试了几遍.发现一直报错. 然后我这才看了一下,安装Cocoapods的日志,发现抛出了一个报错. ...

  2. DataGridView.DataSource= list(Of T)

    注:本文样例的代码承接上篇文章:DataTable填充实体类返回泛型集合. 在D层查询完毕之后.我们将DataTable转化为泛型集合.然后经过中间各层,返回U层.到了这里,问题来了.我们这时候要将这 ...

  3. mqtt client python example

    This is a simple example showing how to use the [Paho MQTT Python client](https://eclipse.org/paho/c ...

  4. c语言知识点总结-------静态区、堆、栈、常量区等

    在C语言中地址占4个字节 1.编程语言发展 低级语言----->高级语言 机器语言 ---> 汇编---->高级语言(C语言.C++.JAVA等) 机器语言 :0101 0010 1 ...

  5. 关于提高沟通能力的书单 | 章鱼书单zz

    上周推荐了一份关于提高写作能力的书单,这周,我们来聊聊沟通能力. 在现代社会,沟通能力变得越来越重要.人与人之间的社交渠道越来越丰富,工作中的协同合作也越来越普遍.我们要沟通的人越来越多,节奏越来越快 ...

  6. (八):构建WineLib DLL

    (一):介绍 出于某些原因,你可能会发现你想要和使用Windows DLL一样使用你的Linux库.对于这有一些原因例如以下: 你正在支持一个使用多个第三方库的大应用.该项目在Linux中是可用的,可 ...

  7. C# 打开指定的目录 记住路径中 / 与 \ 的使用方法

    老生常谈的问题了,C#在指定目录时,路径中要使用 \\.直接看实例 using System; namespace OpenFile{ class OpenFile{ static void Main ...

  8. ArrayList概述

    一. ArrayList概述: ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境 ...

  9. EasyDarwin开源流媒体服务器支持basic基本认证和digest摘要认证解析

    本文转自EasyDarwin开源团队成员ss的博客:http://blog.csdn.net/ss00_2012/article/details/52262621 RTSP认证作为RTSP标准协议的一 ...

  10. 九度OJ 1105:字符串的反码 (翻译)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4929 解决:1529 题目描述: 一个二进制数,将其每一位取反,称之为这个数的反码.下面我们定义一个字符的反码.如果这是一个小写字符,则它 ...