题目:

http://www.lydsy.com/JudgeOnline/problem.php?id=3091

题解:

首先前三个操作就是裸的LCT模板

只考虑第四个操作.

要求我们计算期望,所以我们考虑计算出所有情况的和然后在除以情况的数目.

这样我们就找到分子分母了.

我们很容易发现分母即为\(\frac{n*(n+1)}{2}\)

对应到我们的Splay树上即\(\frac{siz*(siz+1)}{2}\)

所以我们现在考虑维护分子:

对于首先我们考虑在一个长为n的序列上统计这些东西

我们知道总和即为每一项乘以这一项出现的次数(又在废话)

出现的次数又是多少呢?

\[ \begin{matrix}
a_1 & a_2 & a_3 & ... & a_i &... & a_n \\
1*n & 2*(n-1) & 3*(n-2) & ...&i*(n-i+1) & ...& n*1 \\
\end{matrix}
\]

所以其实对于每一个元素,出现的次数都是\((\text{左边的}siz+1)*(\text{右边的}siz+1)\)

那么我们考虑合并:

假设这个区间作为合并的左区间,我们设\(w = \text{右区间的}siz+1\)(即这个区间合并后右侧新出现的节点数)

那么按照刚才的思路,所有的数字的后一项都会同时增大即变为:

\[ \begin{matrix}
a_1 & a_2 & a_3 & ... & a_i &... & a_n \\
1*(n+w) & 2*(n-1+w) & 3*(n-2+w) & ...&i*(n-i+1+w) & ...& n*(1+w) \\
\end{matrix}
\]

于是我们发现实际上这段区间的贡献增加了:

\[ \begin{matrix}
a_1 & a_2 & a_3 & ... & a_i &... & a_n \\
1*w & 2*w & 3*w & ...& i*w & ...& n*w \\
\end{matrix}
\]

所以我们记录一个和表示\(1*a_1 + 2*a_2 + 3*a_3 + ... + n*a_n\)即可

利用这个我们就可以维护分子了。啥?? 怎么维护 ??

\(val = ch[0]->val + ch[1]->val + ch[0]->lsum*(ch[1]->siz + 1) + ch[1]->rsum*(ch[0]->siz + 1) + w*(ch[0]->siz + 1)*(ch[1]->siz + 1);\)

其中\(w\)为节点本身的权,\(lsum = \sum_{i=1}^{n}a_i*i\),\(rsum = \sum_{i=1}^{n}a_i*(n-i+1)\)

至于维护\(lsum\)和\(rsum\)的过程.

我们有

\[1*n + 2*(n-1) + 3*(n-2) + ... + n*1 = \frac{n*(n+1)*(n+2)}{6}
\]

据说是小学数学难度.

夭折啊 !我想不出来 !

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef unsigned long long ll;
  6. inline void read(ll &x){
  7. x=0;char ch;bool flag = false;
  8. while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
  9. while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
  10. }
  11. const ll maxn = 50010;
  12. struct Node{
  13. Node *ch[2],*fa;
  14. ll w,lsum,rsum,lazy;
  15. ll val,siz,tag,sum;
  16. void update();
  17. void pushdown();
  18. void rev();
  19. void inc(ll x);
  20. }*null;
  21. void Node::rev(){
  22. if(this == null) return;
  23. swap(lsum,rsum);swap(ch[0],ch[1]);
  24. tag ^= 1;
  25. }
  26. void Node::inc(ll x){
  27. if(this == null) return;
  28. w += x;sum += x*siz;
  29. lsum += x*siz*(siz+1)/2;
  30. rsum += x*siz*(siz+1)/2;
  31. val += x*siz*(siz+1)*(siz+2)/6;
  32. lazy += x;
  33. }
  34. void Node::pushdown(){
  35. if(this == null) return;
  36. if(lazy){
  37. if(ch[0] != null) ch[0]->inc(lazy);
  38. if(ch[1] != null) ch[1]->inc(lazy);
  39. lazy = 0;
  40. }
  41. if(tag){
  42. if(ch[0] != null) ch[0]->rev();
  43. if(ch[1] != null) ch[1]->rev();
  44. tag = 0;
  45. }
  46. }
  47. void Node::update(){
  48. if(this == null) return;
  49. siz = ch[0]->siz + ch[1]->siz + 1;
  50. sum = ch[0]->sum + ch[1]->sum + w;
  51. lsum = ch[0]->lsum + w*(ch[0]->siz + 1) + ch[1]->lsum + ch[1]->sum*(ch[0]->siz + 1);
  52. rsum = ch[1]->rsum + w*(ch[1]->siz + 1) + ch[0]->rsum + ch[0]->sum*(ch[1]->siz + 1);
  53. val = ch[0]->val + ch[1]->val + ch[0]->lsum*(ch[1]->siz + 1) + ch[1]->rsum*(ch[0]->siz + 1) + w*(ch[0]->siz + 1)*(ch[1]->siz + 1);
  54. }
  55. Node mem[maxn],*it;
  56. inline void init(){
  57. it = mem;null = it++;
  58. null->ch[0] = null->ch[1] = null->fa = null;
  59. null->w = null->lsum = null->rsum = null->sum =
  60. null->val = null->siz = null->tag = 0;
  61. }
  62. inline Node* newNode(ll x){
  63. Node *p = it++;p->ch[0] = p->ch[1] = p->fa = null;
  64. p->w = p->val = p->lsum = p->rsum = p->sum = x;p->siz = 1;
  65. p->tag = p->lazy = 0;
  66. return p;
  67. }
  68. inline void rotate(Node *p,Node *x){
  69. ll k = p == x->ch[1];
  70. Node *y = p->ch[k^1],*z = x->fa;
  71. if(z->ch[0] == x) z->ch[0] = p;
  72. if(z->ch[1] == x) z->ch[1] = p;
  73. if(y != null) y->fa = x;
  74. p->fa = z;p->ch[k^1] = x;
  75. x->fa = p;x->ch[k] = y;
  76. x->update();p->update();
  77. }
  78. inline bool isRoot(Node *p){
  79. return (p == null) || (p->fa->ch[0] != p && p->fa->ch[1] != p);
  80. }
  81. inline void Splay(Node *p){
  82. p->pushdown();
  83. while(!isRoot(p)){
  84. Node *x = p->fa,*y = x->fa;
  85. y->pushdown();x->pushdown();p->pushdown();
  86. if(isRoot(x)) rotate(p,x);
  87. else if((p == x->ch[0])^(x == y->ch[0])) rotate(p,x),rotate(p,y);
  88. else rotate(x,y),rotate(p,x);
  89. }p->update();
  90. }
  91. inline Node* Access(Node *x){
  92. for(Node *y = null;x != null;y = x,x = x->fa)
  93. Splay(x),x->ch[1] = y,x->update();
  94. return x;
  95. }
  96. inline void makeRoot(Node *x){
  97. Access(x);Splay(x);x->rev();
  98. }
  99. inline void link(Node *x,Node *y){
  100. makeRoot(x);x->fa = y;
  101. }
  102. inline void cut(Node *x,Node *y){
  103. makeRoot(x);Access(y);Splay(y);
  104. if(y->ch[0] == x && x->ch[1] == null){
  105. y->ch[0] = y->ch[0]->fa = null;
  106. y->update();
  107. }
  108. }
  109. inline void inc(Node *x,Node *y,ll w){
  110. makeRoot(x);Access(y);Splay(y);
  111. y->inc(w);
  112. }
  113. inline ll gcd(const ll &a,const ll &b){return b == 0 ? a : gcd(b,a%b);}
  114. inline ll query(Node *x,Node *y){
  115. makeRoot(x);Access(y);Splay(y);
  116. ll upside = y->val;
  117. ll dnside = y->siz*(y->siz + 1)/2;
  118. ll g = gcd(upside,dnside);
  119. printf("%llu/%llu\n",upside/g,dnside/g);
  120. }
  121. inline Node* findRoot(Node *x){
  122. Access(x);Splay(x);
  123. while(x->ch[0] != null) x = x->ch[0];
  124. Splay(x);return x;
  125. }
  126. int main(){
  127. init();
  128. ll n,m;read(n);read(m);
  129. for(ll i=1,x;i<=n;++i){
  130. read(x);newNode(x);
  131. }
  132. ll u,v;
  133. for(ll i=1;i<n;++i){
  134. read(u);read(v);
  135. link(mem+u,mem+v);
  136. }
  137. ll op;
  138. while(m--){
  139. read(op);
  140. if(op == 1){
  141. read(u);read(v);
  142. if(u != v && findRoot(mem+u) == findRoot(mem+v)) cut(mem+u,mem+v);
  143. }else if(op == 2){
  144. read(u);read(v);
  145. if(findRoot(mem+u) != findRoot(mem+v)) link(mem+u,mem+v);
  146. }else if(op == 3){
  147. read(u);read(v);read(op);
  148. if(findRoot(mem+u) == findRoot(mem+v)) inc(mem+u,mem+v,op);
  149. }else if(op == 4){
  150. read(u);read(v);
  151. if(findRoot(mem+u) == findRoot(mem+v)) query(mem+u,mem+v);
  152. else puts("-1");
  153. }
  154. }
  155. getchar();getchar();
  156. return 0;
  157. }

bzoj 3091: 城市旅行 LCT的更多相关文章

  1. BZOJ 3091: 城市旅行 [LCT splay 期望]

    3091: 城市旅行 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1454  Solved: 483[Submit][Status][Discuss ...

  2. BZOJ 3091: 城市旅行 lct 期望 splay

    https://www.lydsy.com/JudgeOnline/problem.php?id=3091 https://blog.csdn.net/popoqqq/article/details/ ...

  3. bzoj 3091 城市旅行(LCT+数学分析)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3091 [思路] 膜Popoqqq大爷的题解 click here [代码]是坑... ...

  4. BZOJ 3091 城市旅行

    Description Input Output Sample Input 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 Sample ...

  5. 【BZOJ3091】城市旅行 LCT

    [BZOJ3091]城市旅行 Description Input Output Sample Input 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 ...

  6. 【BZOJ】3091: 城市旅行 Link-Cut Tree

    [题意]参考PoPoQQQ. 给定一棵树,每个点有一个点权,提供四种操作: 1.删除两点之间的连边 不存在边则无视 2.在两点之前连接一条边 两点已经联通则无视 3.在两点之间的路径上所有点的点权加上 ...

  7. bzoj3091 城市旅行 LCT + 区间合并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3091 题解 调了整个晚自习才调出来的问题. 乍一看是个 LCT 板子题. 再看一眼还是个 LC ...

  8. BZOJ3091城市旅行——LCT区间信息合并

    题目描述 输入 输出 样例输入 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 样例输出 16/3 6/1 提示 对于所有数据满足 1& ...

  9. 【bzoj3091】城市旅行 LCT区间合并

    题目描述 输入 输出 样例输入 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 样例输出 16/3 6/1 题解 LCT区间合并 前三个 ...

随机推荐

  1. Myecplise Tomcat 启动很慢

    今天突然遇到一个问题,tomcat在Myecplse启动非常慢,直接用tomcat自带的start.bat启动很快,如果通过Myeclipse启动会发现项目一直在实例化,最后发现是因为加了断点调试,断 ...

  2. Asp.Net MVC3中如何进行单元测试?

    下面我们就以一个示例演示一下如何进行单元测试? public Model.UserInfo UpdateEntity(Model.UserInfo entity) { db.UserInfo.Atta ...

  3. 默写一个socket客户端和socket服务端的基本通信,即:收发消息

    Server: import socket sk = socket.socket() sk.bind(('192.168.0.95',8898)) #把地址绑定到套接字 sk.listen() #监听 ...

  4. Jquery点击事件出发顺序

    鼠标点击触发事件执行顺序: mouse down -> mouse up -> click 键盘点击出发事件执行顺序: 点击后马上抬起:key down -> key press - ...

  5. python cookbook第三版学习笔记十六:抽象基类

    假设一个工程中有多个类,每个类都通过__init__来初始化参数.但是可能有很多高度重复且样式相同的__init__.为了减少代码.我们可以将初始化数据结构的步骤归纳到一个单独的__init__函数中 ...

  6. date_default_timezone_get():

    [Symfony\Component\Debug\Exception\ContextErrorException]                      Warning: date_default ...

  7. 每天一个Linux命令(7)pwd命令

    pwd命令以绝对路径的方式显示用户当前工作目录.命令将当前目录的全路径名称(从根目录)写入标准输出.全部目录使用/分隔.第一个/表示根目录,最后一个目录是当前目录.     (1)用法介绍: pwd[ ...

  8. Example 1 - XY plots

    http://www.ncl.ucar.edu/Document/Manuals/Getting_Started/Examples/gsun01n.shtml Frame 1 Frame 2 Fram ...

  9. 【leetnode刷题笔记】Maximum Depth of binary tree

    Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...

  10. mysql高可用研究(一) 主从+MHA架构

    最近在研究mysql的高可用架构,自己想总结下常用的高可用方案都有哪些.有哪些优缺点以及应用的场景?搞得是头昏脑涨,天昏地暗,看了诸多资料,每次都觉得公说公有理婆说婆有理.其实嘛,大家说的都有一定的道 ...