题目描述

给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林;询问一个点能到达的最远的点与该点的距离。强制在线。

$n\le 3\times 10^5$ ,$m\le 5\times 10^5$ 。


题解

树的直径+并查集+LCT

与直径相关的结论1:与一个点距离最大的点为任意一条直径的两个端点之一。

与直径相关的结论2:两棵树之间连一条边,新树直径的两个端点一定为第一棵树直径的两个端点和第二棵树直径的两个端点这四者中之二。

于是问题就变简单了,用并查集维护每个连通块的直径即可。由于强制在线,所以必须用LCT维护树上距离。

时间复杂度 $O(LCT·n\log n)=O(能过)$

  1. #include <cstdio>
  2. #include <algorithm>
  3. #define N 300010
  4. using namespace std;
  5. int f[N] , px[N] , py[N] , fa[N] , c[2][N] , si[N] , rev[N];
  6. int find(int x)
  7. {
  8. return x == f[x] ? x : f[x] = find(f[x]);
  9. }
  10. inline void pushup(int x)
  11. {
  12. si[x] = si[c[0][x]] + si[c[1][x]] + 1;
  13. }
  14. inline void pushdown(int x)
  15. {
  16. if(rev[x])
  17. {
  18. swap(c[0][c[0][x]] , c[1][c[0][x]]) , rev[c[0][x]] ^= 1;
  19. swap(c[0][c[1][x]] , c[1][c[1][x]]) , rev[c[1][x]] ^= 1;
  20. rev[x] = 0;
  21. }
  22. }
  23. inline bool isroot(int x)
  24. {
  25. return x != c[0][fa[x]] && x != c[1][fa[x]];
  26. }
  27. void update(int x)
  28. {
  29. if(!isroot(x)) update(fa[x]);
  30. pushdown(x);
  31. }
  32. inline void rotate(int x)
  33. {
  34. int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
  35. if(!isroot(y)) c[c[1][z] == y][z] = x;
  36. fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
  37. pushup(y) , pushup(x);
  38. }
  39. inline void splay(int x)
  40. {
  41. int y , z;
  42. update(x);
  43. while(!isroot(x))
  44. {
  45. y = fa[x] , z = fa[y];
  46. if(!isroot(y))
  47. {
  48. if((c[0][y] == x) ^ (c[0][z] == y)) rotate(x);
  49. else rotate(y);
  50. }
  51. rotate(x);
  52. }
  53. }
  54. inline void access(int x)
  55. {
  56. int t = 0;
  57. while(x) splay(x) , c[1][x] = t , pushup(x) , t = x , x = fa[x];
  58. }
  59. inline void makeroot(int x)
  60. {
  61. access(x) , splay(x) , swap(c[0][x] , c[1][x]) , rev[x] ^= 1;
  62. }
  63. inline int dis(int x , int y)
  64. {
  65. makeroot(x) , access(y) , splay(y);
  66. return si[y];
  67. }
  68. inline void link(int x , int y)
  69. {
  70. int tx = find(x) , ty = find(y) , mx = -1 , t , rx , ry;
  71. makeroot(x) , fa[x] = y;
  72. if(mx < (t = dis(px[tx] , py[tx]))) mx = t , rx = px[tx] , ry = py[tx];
  73. if(mx < (t = dis(px[ty] , py[ty]))) mx = t , rx = px[ty] , ry = py[ty];
  74. if(mx < (t = dis(px[tx] , px[ty]))) mx = t , rx = px[tx] , ry = px[ty];
  75. if(mx < (t = dis(px[tx] , py[ty]))) mx = t , rx = px[tx] , ry = py[ty];
  76. if(mx < (t = dis(py[tx] , px[ty]))) mx = t , rx = py[tx] , ry = px[ty];
  77. if(mx < (t = dis(py[tx] , py[ty]))) mx = t , rx = py[tx] , ry = py[ty];
  78. f[tx] = ty , px[ty] = rx , py[ty] = ry;
  79. }
  80. int main()
  81. {
  82. int type , n , q , i , opt , x , y , ans = 0;
  83. scanf("%d%d%d" , &type , &n , &q);
  84. for(i = 1 ; i <= n ; i ++ ) f[i] = px[i] = py[i] = i , si[i] = 1;
  85. while(q -- )
  86. {
  87. scanf("%d%d" , &opt , &x) , x ^= ans;
  88. if(opt == 1) scanf("%d" , &y) , y ^= ans , link(x , y);
  89. else y = find(x) , printf("%d\n" , ans = max(dis(x , px[y]) , dis(x , py[y])) - 1);
  90. if(!type) ans = 0;
  91. }
  92. return 0;
  93. }

【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT的更多相关文章

  1. loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...

  2. [loj6038]「雅礼集训 2017 Day5」远行 lct+并查集

    给你 n 个点,支持 m 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. n≤3×10^5 n≤3×10^5 ,m≤5×10^5 m≤5 ...

  3. LOJ#6038. 「雅礼集训 2017 Day5」远行(LCT)

    题面 传送门 题解 要不是因为数组版的\(LCT\)跑得实在太慢我至于去学指针版的么--而且指针版的完全看不懂啊-- 首先有两个结论 1.与一个点距离最大的点为任意一条直径的两个端点之一 2.两棵树之 ...

  4. 【刷题】LOJ 6038 「雅礼集训 2017 Day5」远行

    题目描述 Miranda 生活的城市有 \(N\) 个小镇,一开始小镇间没有任何道路连接.随着经济发现,小镇之间陆续建起了一些双向的道路但是由于经济不太发达,在建设过程中,会保证对于任意两个小镇,最多 ...

  5. 「雅礼集训 2017 Day5」远行

    题目链接 问题分析 要求树上最远距离,很显然就想到了树的直径.关于树的直径,有下面几个结论: 如果一棵树的直径两个端点为\(a,b\),那么树上一个点\(v\)开始的最长路径是\(v\rightarr ...

  6. loj#6038 「雅礼集训 2017 Day5」远行

    分析 代码 #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define ...

  7. LOJ#6038. 「雅礼集训 2017 Day5」远行 [LCT维护子树的直径]

    树的直径一定是原联通块4个里的组合 1.LCT,维护树的直径,这题就做完了 2.直接倍增,lca啥的求求距离,也可以吧- // powered by c++11 // by Isaunoya #inc ...

  8. 「雅礼集训 2017 Day5」珠宝

    题目描述 Miranda 准备去市里最有名的珠宝展览会,展览会有可以购买珠宝,但可惜的是只能现金支付,Miranda 十分纠结究竟要带多少的现金,假如现金带多了,就会比较危险,假如带少了,看到想买的右 ...

  9. 「雅礼集训 2017 Day5」矩阵

    填坑填坑.. 感谢wwt耐心讲解啊.. 如果要看这篇题解建议从上往下读不要跳哦.. 30pts 把$A$和$C$看成$n$个$n$维向量,那$A_i$是否加入到$C_j$中就可以用$B_{i,j}$表 ...

随机推荐

  1. 20155330 2016-2017-2 《Java程序设计》第九周学习总结

    20155330 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 学习目标 了解JDBC架构 掌握JDBC架构 掌握反射与ClassLoader 了解自定义泛 ...

  2. 20155338 《JAVA程序设计》实验五网络编程与安全实验报告

    20155338 <JAVA程序设计>实验五网络编程安全实验报告 实验内容 实验一: •两人一组结对编程: •结对实现中缀表达式转后缀表达式的功能 MyBC.java •结对实现从上面功能 ...

  3. 北京Uber优步司机奖励政策(4月10日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. 【SQLSERVER】索引的维护优化

    一.索引的利弊   优点: 1.大大加快数据的检索速度: 2.创建唯一性索引,保证数据库表中每一行数据的唯一性: 3.加速表和表之间的连接: 4.在使用分组和排序子句进行数据检索时,可以显著减少查询中 ...

  5. MySQL主从失败报错误: Got fatal error 1236

    一.问题原因及报错误信息 由于MySQL主库意外重启,导致从库无法同步报错如下: 登录从库查看主从同步的错误信息 [root@--- mysql]# vim mysqld-error.log -- : ...

  6. Zabbix学习之路(九)之低级自动发现以及MySQL多实例

    1.概述 Zabbix的网络发现是指zabbix server通过配置好的规则,自动添加host,group,template Zabbix的主动注册刚好和网络发现是相反的,功能基本一致.zabbix ...

  7. Session丢失——解决方案

    先抄下别人的作业(原帖:http://www.cnblogs.com/zhc088/archive/2011/07/24/2115497.html) Session丢失已经是一种习以为常的问题了,在自 ...

  8. 解决老项目中 Timer运行一段时间后失效的问题

    那是因为Timer中的代码出现了异常未被捕获,所以线程被挂起 只需要加入  try catch即可 推荐使用 Quartz 2018-08-08 03:50:44 [ Timer-1:39366015 ...

  9. L016-linux系统文件权限体系实战深入讲解小节

    L016-linux系统文件权限体系实战深入讲解小节 不知道今天能不能写完哈,能写完发出来就是这周发两次小结了,有进步哦,不过L015和L016两节课内容也确实不多,进入正题 上一课学到了chmod. ...

  10. Pycharm主菜单学习

    “工欲善其事,必先利其器”,这话我一直是这么坚信的! 找到一款顺手称心的工具,拥有它,熟练地使用它! Pycharm据说就是使用Python的一款最好的工具—— 于是,开始了第一步的学习----先从熟 ...