一道好题~~

  一个点到根传染需要的时间是这段路径上不同颜色的数目,一个点子树到根平均传染时间就是加权平均数了(好像是废话)。

  所以只要用线段树维护dfs序就这个可以了,换根的话一个点的子树要么在dfs序中不变,要么被截成了[1,l)和(r,n]两段(当这个点为当前root的祖先),l和r即为包含当前根的这个点的那个儿子的dfs序中的st和ed,只要分类讨论一下就可以了。

  所以问题只剩什么时候在线段树上修改,我们发现1操作和LCT中的access操作很像,2操作就是make_root,每个splay就是一个相同的颜色段,那么一个点到根的距离就是LCT中虚边的个数,把虚边改实边子树-1,反过来子树+1,而LCT的复杂度是nlogn的,那直接做就好了。

  

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #define N 100005
  6. #define ll long long
  7. using namespace std;
  8. int head[N],nxt[N*],ver[N*],tot;int n,m;
  9. void addd(int a,int b)
  10. {
  11. tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
  12. }
  13. int rev[N],ch[N][],root,L[N],R[N],fa[N],faa[N];
  14. bool isroot(int x)
  15. {
  16. return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;
  17. }
  18. void push_down(int x)
  19. {
  20. if(rev[x])
  21. {
  22. rev[x]^=;rev[ch[x][]]^=;rev[ch[x][]]^=;
  23. swap(L[ch[x][]],R[ch[x][]]);
  24. swap(L[ch[x][]],R[ch[x][]]);
  25. swap(ch[x][],ch[x][]);
  26. }
  27. return ;
  28. }
  29. void push_up(int x)
  30. {
  31. if(!ch[x][])L[x]=x;
  32. else L[x]=L[ch[x][]];
  33. if(!ch[x][])R[x]=x;
  34. else R[x]=R[ch[x][]];
  35. }
  36. void rotate(int p)
  37. {
  38. int q=fa[p],y=fa[q],x=(ch[q][]==p);
  39. ch[q][x]=ch[p][x^];fa[ch[q][x]]=q;
  40. ch[p][x^]=q;
  41. fa[p]=y;
  42. if(!isroot(q))
  43. {
  44. if(ch[y][]==q)ch[y][]=p;
  45. else ch[y][]=p;
  46. }
  47. fa[q]=p;
  48. push_up(q);
  49. }
  50. int q[N],topp;
  51. void splay(int x)
  52. {
  53. q[++topp]=x;
  54. for(int i=x;!isroot(i);i=fa[i])q[++topp]=fa[i];
  55. while(topp)push_down(q[topp--]);
  56. for(int y;!isroot(x);rotate(x))
  57. {
  58. y=fa[x];
  59. if(!isroot(y))
  60. {
  61. if((ch[fa[y]][]==y)^(ch[y][]==x))rotate(x);
  62. else rotate(y);
  63. }
  64. }
  65. push_up(x);
  66. }
  67. struct node
  68. {
  69. ll lazy,sum;
  70. }a[N*];
  71. int sz[N];
  72. int st[N],ed[N],z,jian[N],dep[N],top[N],son[N];
  73. int find(int x,int y)
  74. {
  75. while(top[y]!=top[x])
  76. {
  77. if(faa[top[y]]==x)return top[y];
  78. y=faa[top[y]];
  79. }
  80. return son[x];
  81. }
  82. void dfs(int x,int f)
  83. {
  84. st[x]=++z;jian[z]=dep[x];sz[x]=;L[x]=R[x]=x;
  85. for(int i=head[x];i;i=nxt[i])
  86. {
  87. if(ver[i]==f)continue;
  88. fa[ver[i]]=x;dep[ver[i]]=dep[x]+;faa[ver[i]]=x;
  89.  
  90. dfs(ver[i],x);
  91. sz[x]+=sz[ver[i]];
  92. if(sz[ver[i]]>sz[son[x]])son[x]=ver[i];
  93. }
  94. ed[x]=z;
  95. return ;
  96. }
  97. void dffs(int x,int f,int tp)
  98. {
  99. top[x]=tp;
  100. if(son[x])dffs(son[x],x,tp);
  101. for(int i=head[x];i;i=nxt[i])
  102. {
  103. if(ver[i]==f||ver[i]==son[x])continue;
  104. dffs(ver[i],x,ver[i]);
  105. }
  106. }
  107. void pd(int x,int l,int mid,int r)
  108. {
  109. if(a[x].lazy)
  110. {
  111. a[x*].sum+=a[x].lazy*(mid-l+);
  112. a[x*+].sum+=a[x].lazy*(r-mid);
  113. a[x*].lazy+=a[x].lazy;a[x*+].lazy+=a[x].lazy;
  114. a[x].lazy=;
  115. }return ;
  116. }
  117. ll qur(int x,int l,int r,int lll,int rr)
  118. {
  119. if(rr<lll)return ;
  120. if(lll<=l&&rr>=r)
  121. {
  122. return a[x].sum;
  123. }
  124. int mid=(l+r)>>;
  125. pd(x,l,mid,r);
  126. if(lll>mid)return qur(x*+,mid+,r,lll,rr);
  127. if(rr<=mid)return qur(x*,l,mid,lll,rr);
  128. return qur(x*,l,mid,lll,rr)+qur(x*+,mid+,r,lll,rr);
  129. }
  130. void add(int x,int l,int r,int lll,int rr,ll z)
  131. {
  132. if(rr<lll)return ;
  133. if(lll<=l&&rr>=r)
  134. {
  135. a[x].sum+=z*(r-l+);
  136. a[x].lazy+=z;
  137. return ;
  138. }
  139. int mid=(l+r)>>;
  140. pd(x,l,mid,r);
  141. if(lll<=mid)add(x*,l,mid,lll,rr,z);
  142. if(rr>mid)add(x*+,mid+,r,lll,rr,z);
  143. a[x].sum=a[x*].sum+a[x*+].sum;
  144. }
  145. void build(int x,int l,int r)
  146. {
  147. if(l==r)
  148. {
  149. a[x].sum=jian[l];
  150. return ;
  151. }
  152. int mid=(l+r)>>;
  153. build(x*,l,mid);build(x*+,mid+,r);
  154. a[x].sum=a[x*].sum+a[x*+].sum;
  155. return ;
  156. }
  157. void gao(int x,int z)
  158. {
  159. if(x==root)
  160. {
  161. add(,,n,,n,z);
  162. }
  163. else if(st[x]<st[root]&&ed[x]>=ed[root])
  164. {
  165. int t=find(x,root);
  166. add(,,n,,st[t]-,z);
  167. add(,,n,ed[t]+,n,z);
  168. }
  169. else
  170. {
  171. add(,,n,st[x],ed[x],z);
  172. }
  173. }
  174. void access(int x)
  175. {
  176. for(int t=;x;t=x,x=fa[x])
  177. {
  178. splay(x);
  179. if(t)gao(L[t],-);
  180. if(ch[x][])
  181. {
  182. gao(L[ch[x][]],);
  183. }
  184. ch[x][]=t;
  185. push_up(x);
  186. }
  187. return ;
  188. }
  189. void make_root(int x)
  190. {
  191. access(x);splay(x);
  192. rev[x]^=;swap(L[x],R[x]);
  193. return ;
  194. }
  195. int qursize(int x)
  196. {
  197. if(x==root)return n;
  198. if(st[x]<st[root]&&ed[x]>=ed[root])
  199. {
  200. int t=find(x,root);
  201. return n-sz[t];
  202. }
  203. else return sz[x];
  204. }
  205. ll qurs(int x)
  206. {
  207. if(x==root)return qur(,,n,,n);
  208. if(st[x]<st[root]&&ed[x]>=ed[root])
  209. {
  210. int t=find(x,root);
  211. return qur(,,n,,st[t]-)+qur(,,n,ed[t]+,n);
  212. }
  213. return qur(,,n,st[x],ed[x]);
  214. }
  215. int main()
  216. {
  217. scanf("%d%d",&n,&m);
  218. int t1,t2;
  219. for(int i=;i<n;i++)
  220. {
  221. scanf("%d%d",&t1,&t2);
  222. addd(t1,t2);addd(t2,t1);
  223. }
  224. dep[]=;
  225. dfs(,-);
  226. build(,,n);
  227. dffs(,-,);
  228. char c[];root=;int tmp;
  229. for(int i=;i<=m;i++)
  230. {
  231. scanf("%s",c+);
  232. scanf("%d",&tmp);
  233. if(c[]=='Q')
  234. {
  235. int size=qursize(tmp);
  236. ll ss=qurs(tmp);
  237. printf("%.10lf\n",((double)ss)/size);
  238. }
  239. else if(c[]=='L')
  240. {
  241. access(tmp);
  242.  
  243. }
  244. else
  245. {
  246. make_root(tmp);
  247. root=tmp;
  248. }
  249. }
  250. return ;
  251. }

  

bzoj 3779: 重组病毒的更多相关文章

  1. bzoj 3779: 重组病毒 LCT+线段树+倍增

    题目: 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒. 实验在一个封闭 ...

  2. BZOJ 3779: 重组病毒(线段树+lct+树剖)

    题面 escription 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病 ...

  3. BZOJ 3779 重组病毒 LCT+线段树(维护DFS序)

    原题干(由于是权限题我就直接砸出原题干了,要看题意概述的话在下面): Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力 ...

  4. bzoj 3779 重组病毒——LCT维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 调了很久……已经懒得写题解了.https://www.cnblogs.com/Zinn ...

  5. bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...

  6. bzoj 3779: 重组病毒【LCT+线段树维护dfs序】

    %.8lf会WA!!%.8lf会WA!!%.8lf会WA!!要%.10lf!! 和4817有点像,但是更复杂. 首先对于操作一"在编号为x的计算机中植入病毒的一个新变种,在植入一个新变种时, ...

  7. bzoj 3779 重组病毒 好题 LCT+dfn序+线段树分类讨论

    题目大意 1.将x到当前根路径上的所有点染成一种新的颜色: 2.将x到当前根路径上的所有点染成一种新的颜色,并且把这个点设为新的根: 3.查询以x为根的子树中所有点权值的平均值. 分析 原题codec ...

  8. BZOJ 3779 重组病毒 ——LCT 线段树

    发现操作一很像一个LCT的access的操作. 然后答案就是路径上的虚边的数量. 然后考虑维护每一个点到根节点虚边的数量, 每次断开一条偏爱路径的时候,子树的值全部+1, 连接一条偏爱路径的时候,子树 ...

  9. 【BZOJ】3779 重组病毒

    [算法]Link-Cut Tree+线段树(维护DFS序) [题解]整整三天……T_T 这篇题解比较资瓷:permui 这道题虽然树形态没有变化,但用lct写的原因在于把题目中的操作一进行了神转化:每 ...

随机推荐

  1. Windows ,获取硬盘物理序列号(VC++)

    #include <windows.h> BOOL GetHDID(PCHAR pIDBufer) {     HANDLE hDevice=NULL;    hDevice=::Crea ...

  2. Google hack语法

    基础语法: 1.语法说明: inurl: 在url地址栏中显示的信息页面 intext: 显示在正文信息中的内容页面 site: 限制显示你某个域名的所有页面 filetype: 搜索文件的后缀或者扩 ...

  3. 详细教你实现BST(二叉排序树)

    查找基本分类如下: 线性表的查找 顺序查找 折半查找 分块查找 树表的查找 二叉排序树 平衡二叉树 B树 B+树 散列表的查找 今天介绍二叉排序树. 二叉排序树 ( Binary Sort Tree ...

  4. 浅谈jQuery构造函数

    $()函数到底做的什么 jQuery在前端领域路人皆知,对于一向喜欢玩js的博主来说,虽然能力有限,但是还是很喜欢研究他的做为.那么一个简单的美元符号$与一对常见的()括号,jQuery底层到底做了哪 ...

  5. 获取session

    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()) ...

  6. 团队博客作业Week4 --- 学霸网站--NABC

    1.需求(Need) 伴随着经济的发展,科学技术取得了飞速的发展,互联网在各行各业的发展中取得了广泛的应用.随着这些事物的发展,我们每个人都会接触到相当庞大的数据.如何在这些数据中找到自己需要的,如何 ...

  7. No.100_第一次团队会议

    任务的确立 这次会议,我们的主要目标是确定任务: 我们的任务有以下几个选择: 学霸网站,这个项目拥有以前的前端代码,我们再使用Django后端服务.上手难度较低,环境较好. 多平台时间管理软件. 安卓 ...

  8. StringBuffer 与 StringBuilder类的使用

    /*如果需要频繁修改字符串 的内容,建议使用字符串缓冲 类(StringBuffer). StringBuffer 其实就是一个存储字符 的容器. 笔试题目:使用Stringbuffer无 参的构造函 ...

  9. Journal entry of the thirteenth chapter to chapter seventeenth(第十三章和十七章阅读与疑问)

    第十三章: 软件测试的意义在于: a.     发现软件错误: b.     有效定义和实现软件成分由低层到高层的组装过程: c.     验证软件是否满足任务书和系统定义文档所规定的技术要求: d. ...

  10. 索引超出了数组界限。 在 System.Collections.Generic.Dictionary`2.Resize

    博问:Dictionary 超出了数组界限 异常: Exception type: IndexOutOfRangeException Exception message: 索引超出了数组界限. 在 S ...