一、题目

点此看题

二、解法

题目的提示已经足够明显了吧,肯定是要写一个 \(\tt link-cut-tree\) 。我们只需要求出总和,再除以方案数就是期望。然后可以算每个点为 \(\tt lca\) 时的贡献。

但是要对子树搞点事情,而子树分为虚子树和实子树(看连接的是什么边),所以两类都要维护,实子树可以用 \(\tt push\_up\) 操作维护,虚子树要在变动父子关系的时候维护,有点麻烦。要维护下列信息:

  • \(x\) 的虚子树大小(包括 \(x\) 这个点):\(siz\)
  • \(x\) 的子树中节点总个数:\(sum\)
  • \(x\) 节点包括其子树中的每个点的答案和:\(ans\)
  • \(x\) 子树内所有点的 \(siz\times a\) :\(all\)
  • \(x\) 所有虚子树的答案:\(ad\)
  • \(x\) 所有虚子树 \(siz\) 的平方求和:\(de\)

虚子树的信息你肯定是会维护的,\(sum\) 和 \(ans\) 你肯定也会,我就来详细讲一讲 \(ans\) 怎么算,要分成四部分:

  • 拿到其子树的答案:\(ans[ls]+ans[rs]+ad[x]\)
  • 虚子树之间的贡献,也就是在 \(siz[x]\) 中乱选两个点,再把两点选在同一个子树中的方案给删掉:\((siz[x]\times siz[x]-de[x])\times a[x]\)
  • 虚子树和实子树(\(x\) 的右儿子)之间的贡献,它们的 \(\tt lca\) 是 \(x\):\(2\times a[x]\times siz[x]\times sum[ch[x][1]]\)
  • \(x\) 的子树和 \(x\) 祖先的贡献(\(x\) 的左儿子),这个贡献由于 \(\tt splay\) 结构的原因没有被统计到,反正是求总和,我们把这个贡献放在 \(x\) 这里也没关系:\(2\times all[ch[x][0]]\times (sum[x]-sum[ch[x][0]])\)

然后因为要保证是有根树所以不能用 \(\tt makeroot\) 。那么 \(\tt link(x,y)\) 就把 \(x,y\) 都转到根然后连虚边,\(\tt cut\) 就把 \(x\) 转到根,\(y\) 转到 \(x\) 下面然后删虚边。在 \(\tt access,cut,link\) 的时候都要改虚子树的信息哦。

反正写的时候就是非常爽,非常爽。

  1. #include <cstdio>
  2. #include <iostream>
  3. using namespace std;
  4. const int M = 50005;
  5. #define int long long
  6. int read()
  7. {
  8. int x=0,f=1;char c;
  9. while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
  10. while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
  11. return x*f;
  12. }
  13. int n,m,a[M],siz[M],sum[M],ans[M];char s[10];
  14. int fa[M],all[M],ad[M],de[M],ch[M][2],par[M];double r;
  15. /*
  16. siz[x]表示x的虚子树大小(包括x)
  17. sum[x]表示x为根的子树节点个数
  18. ans[x]表示x的答案
  19. all[x]表示x子树内的siz[y]*a[y]
  20. ad[x]表示x虚子树的答案
  21. de[x]表示x的虚子树的sum的平方的和
  22. */
  23. void up(int x)
  24. {
  25. sum[x]=siz[x]+sum[ch[x][0]]+sum[ch[x][1]];
  26. all[x]=all[ch[x][0]]+all[ch[x][1]]+a[x]*siz[x];
  27. ans[x]=ans[ch[x][0]]+ans[ch[x][1]]+ad[x]//第一部分,直接累加
  28. +a[x]*(siz[x]*siz[x]-de[x])//第二部分,虚子树的贡献
  29. +2*a[x]*sum[ch[x][1]]*siz[x]//第三部分,虚实之间的贡献,lca是x
  30. +2*all[ch[x][0]]*(sum[x]-sum[ch[x][0]]);//第四部分,把祖先的答案算到它上面
  31. }
  32. int nrt(int x)//判断是不是实边
  33. {
  34. return ch[par[x]][0]==x || ch[par[x]][1]==x;
  35. }
  36. int chk(int x)//判断是哪个儿子
  37. {
  38. return ch[par[x]][1]==x;
  39. }
  40. void rotate(int x)
  41. {
  42. int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
  43. ch[y][k]=w;par[w]=y;
  44. if(nrt(y)) ch[z][chk(y)]=x;par[x]=z;
  45. ch[x][k^1]=y;par[y]=x;
  46. up(y);up(x);
  47. }
  48. void splay(int x)//转到实链的最上面
  49. {
  50. while(nrt(x))
  51. {
  52. int y=par[x];
  53. if(nrt(y))
  54. {
  55. if(chk(x)==chk(y)) rotate(y);
  56. else rotate(x);
  57. }
  58. rotate(x);
  59. }
  60. }
  61. void access(int x)
  62. {
  63. for(int y=0;x;x=par[y=x])
  64. {
  65. splay(x);
  66. //先把ch[x][1]加进虚子树中
  67. siz[x]+=sum[ch[x][1]];
  68. ad[x]+=ans[ch[x][1]];
  69. de[x]+=sum[ch[x][1]]*sum[ch[x][1]];
  70. //再把y从虚子树中拿出来
  71. siz[x]-=sum[y];
  72. ad[x]-=ans[y];
  73. de[x]-=sum[y]*sum[y];
  74. ch[x][1]=y;up(x);
  75. }
  76. }
  77. void link(int x,int y)//把(x,y)连一条边,x是祖先
  78. {
  79. access(y);
  80. splay(y);
  81. access(x);
  82. splay(x);
  83. par[y]=x;
  84. siz[x]+=sum[y];
  85. ad[x]+=ans[y];
  86. de[x]+=sum[y]*sum[y];
  87. up(x);
  88. }
  89. void cut(int x,int y)//把(x,y)这条边去掉,x是祖先
  90. {
  91. access(x);
  92. splay(x);
  93. splay(y);
  94. par[y]=0;
  95. siz[x]-=sum[y];
  96. ad[x]-=ans[y];
  97. de[x]-=sum[y]*sum[y];
  98. up(x);
  99. }
  100. int check(int x,int y)//判断x是不是y的祖先
  101. {
  102. access(y);
  103. splay(y);
  104. splay(x);
  105. return nrt(y);
  106. }
  107. signed main()
  108. {
  109. n=read();
  110. for(int i=2;i<=n;i++)
  111. fa[i]=read();
  112. for(int i=1;i<=n;i++)
  113. {
  114. a[i]=ans[i]=all[i]=read();
  115. siz[i]=sum[i]=1;
  116. }
  117. for(int i=2;i<=n;i++)
  118. link(fa[i],i);
  119. m=read();
  120. access(1);
  121. splay(1);
  122. r=ans[1];
  123. printf("%.10lf\n",r/n/n);
  124. while(m--)
  125. {
  126. scanf("%s",s);
  127. int x=read(),y=read();double r=0;
  128. if(s[0]=='P')
  129. {
  130. if(check(x,y)) swap(x,y);
  131. cut(fa[x],x);
  132. fa[x]=y;
  133. link(fa[x],x);
  134. access(1);
  135. splay(1);
  136. r=ans[1];
  137. }
  138. else
  139. {
  140. access(x);
  141. splay(x);
  142. a[x]=y;
  143. up(x);
  144. r=ans[x];
  145. }
  146. printf("%.10lf\n",r/n/n);
  147. }
  148. }

CF482E ELCA的更多相关文章

  1. 【CF 482E】ELCA

    题意 题解 50pts 由于这题 \(2s\),所以可以信仰一波,暴力修改.查询. 暴力修改的复杂度是 \(O(n)\),暴力查询的复杂度是 \(O(n^2)\). 但不难发现可以通过记录子树大小来优 ...

  2. Codeforces 482E ELCA (LCT)

    题目链接 http://codeforces.com/contest/482/problem/E 题解 T2智商题T3大LCT题,我一个也不会= = CF的标算好像是分块?反正现在LCT都普及了就用L ...

  3. CF数据结构练习

    1. CF 438D The Child and Sequence 大意: n元素序列, m个操作: 1,询问区间和. 2,区间对m取模. 3,单点修改 维护最大值, 取模时暴力对所有>m的数取 ...

  4. CORBA简介

    使用.NET开发corba应用 一. 什么是IIOP.NET IIOP.NET 是通过使用基于corba的IIOP支持.NET.javaEE和corba组件实现无缝互操作的技术.如图1.1所示,这种解 ...

随机推荐

  1. Docker文件挂载总结

    Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定. 譬如我要启动一个centos容器,宿主机的/test目录挂载到容器的/soft目录,可通过以下方式指定: # docker ...

  2. GO - 高级编程

    https://books.studygolang.com/gopl-zh/ https://chai2010.cn/advanced-go-programming-book/

  3. cin 与 getline

    cin空格截断 getline(cin,s) 换行结束 ....太愚蠢了

  4. Leetcode(94)-二叉树的中序遍历

    给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 思路:和上篇的前序遍历一样,同样有递归和非递归的做法 (1)递归 vecto ...

  5. 问题记录 java.lang.NoClassDefFoundError: org/dom4j/DocumentException

    客户端调webservice服务产生以下错误 AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.genera ...

  6. 智能广告投放平台 All in One

    智能广告投放平台 All in One app demos 知之数据 一站式广告营销平台 https://hio.cn/ refs https://www.jonmellman.com/posts/p ...

  7. Chrome Canary crashed bug

    Chrome Canary crashed bug Aw, Snap https://support.google.com/chrome/?p=e_awsnap clear cache, 使用隐身模式 ...

  8. Flutter Hackathon 2020

    Flutter Hackathon 2020 https://flutterhackathon.com/#/ Flutter Day https://mp.weixin.qq.com/s/ux17-A ...

  9. flutter 混合开发

    flutter 混合开发 https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps https://flutter.de ...

  10. Scalability & Scale-up & Scale-out

    Scalability & Scale-up & Scale-out 架构,弹性,伸缩性 Scalability 可扩展性 https://en.wikipedia.org/wiki/ ...