Prelude

快要THUWC了,练一练板子。

传送到LOJ:o(TヘTo)


Solution

首先有一条定理。

到树中任意一点的最远点一定是直径的两个端点之一。

我也不会证反正大家都在用,似乎可以用反证法搞一搞?

然后就是LCT和并查集随便做了。

对于每个连通块,只需要保存这个连通块的直径的两个端点就可以了。

然后合并两个连通块的时候更新一下。


Code

  1. #include <cstring>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cctype>
  5. using namespace std;
  6. const int N = 300010;
  7. int _w;
  8. int read() {
  9. int x = 0, ch;
  10. while( isspace(ch = getchar()) );
  11. do x = x * 10 + ch - '0';
  12. while( isdigit(ch = getchar()) );
  13. return x;
  14. }
  15. int type, n, q, lastans;
  16. namespace LCT {
  17. struct Node {
  18. int sz;
  19. Node *ch[2], *pa, *pathpa;
  20. bool rev;
  21. Node() {
  22. ch[0] = ch[1] = pa = pathpa = NULL;
  23. sz = 1, rev = 0;
  24. }
  25. int relation() {
  26. return this == pa->ch[0] ? 0 : 1;
  27. }
  28. Node *pushdown() {
  29. if( rev ) {
  30. rev = 0;
  31. swap( ch[0], ch[1] );
  32. if( ch[0] ) ch[0]->rev ^= 1;
  33. if( ch[1] ) ch[1]->rev ^= 1;
  34. }
  35. return this;
  36. }
  37. Node *maintain() {
  38. sz = 1;
  39. if( ch[0] ) sz += ch[0]->sz;
  40. if( ch[1] ) sz += ch[1]->sz;
  41. return this;
  42. }
  43. Node *rotate() {
  44. if( pa->pa ) pa->pa->pushdown();
  45. pa->pushdown(), pushdown();
  46. Node *old = pa;
  47. int x = relation();
  48. if( pa->pa ) pa->pa->ch[old->relation()] = this;
  49. pa = pa->pa;
  50. old->ch[x] = ch[x^1];
  51. if( ch[x^1] ) ch[x^1]->pa = old;
  52. ch[x^1] = old, old->pa = this;
  53. swap(old->pathpa, pathpa);
  54. return old->maintain(), maintain();
  55. }
  56. Node *splay() {
  57. while( pa ) {
  58. if( !pa->pa ) rotate();
  59. else {
  60. pa->pa->pushdown(), pa->pushdown();
  61. if( relation() == pa->relation() )
  62. pa->rotate(), rotate();
  63. else rotate(), rotate();
  64. }
  65. }
  66. return this;
  67. }
  68. Node *expose() {
  69. Node *rc = splay()->pushdown()->ch[1];
  70. if( rc ) {
  71. ch[1] = rc->pa = NULL;
  72. rc->pathpa = this;
  73. maintain();
  74. }
  75. return this;
  76. }
  77. bool splice() {
  78. if( !splay()->pathpa ) return false;
  79. pathpa->expose()->ch[1] = this;
  80. pa = pathpa, pathpa = NULL;
  81. pa->maintain();
  82. return true;
  83. }
  84. Node *access() {
  85. expose();
  86. while( splice() );
  87. return this;
  88. }
  89. Node *evert() {
  90. access()->rev ^= 1;
  91. return this;
  92. }
  93. };
  94. Node *rt[N];
  95. void init() {
  96. for( int i = 1; i <= n; ++i )
  97. rt[i] = new Node;
  98. }
  99. void link( int u, int v ) {
  100. rt[u]->evert()->pathpa = rt[v];
  101. }
  102. int query( int u, int v ) {
  103. rt[u]->evert();
  104. return rt[v]->access()->sz - 1;
  105. }
  106. }
  107. namespace DSU {
  108. int pa[N], du[N], dv[N];
  109. void init() {
  110. for( int i = 1; i <= n; ++i )
  111. pa[i] = du[i] = dv[i] = i;
  112. }
  113. int find( int u ) {
  114. return pa[u] == u ? u : pa[u] = find( pa[u] );
  115. }
  116. int uni( int u, int v ) {
  117. u = find(u), v = find(v);
  118. return pa[u] = v;
  119. }
  120. }
  121. namespace Solve {
  122. void init() {
  123. DSU::init();
  124. LCT::init();
  125. }
  126. void link( int u, int v ) {
  127. using DSU::du;
  128. using DSU::dv;
  129. using DSU::find;
  130. int u1 = du[find(u)], u2 = dv[find(u)];
  131. int v1 = du[find(v)], v2 = dv[find(v)];
  132. int w1 = LCT::query(u, u1) > LCT::query(u, u2) ? u1 : u2;
  133. int w2 = LCT::query(v, v1) > LCT::query(v, v2) ? v1 : v2;
  134. LCT::link(u, v);
  135. int rt = DSU::uni(u, v);
  136. int lenu = LCT::query(u1, u2);
  137. int lenv = LCT::query(v1, v2);
  138. int lenw = LCT::query(w1, w2);
  139. // printf( "w1 = %d, w2 = %d, lenw = %d\n", w1, w2, lenw );
  140. if( lenu >= lenv && lenu >= lenw )
  141. du[rt] = u1, dv[rt] = u2;
  142. else if( lenv >= lenu && lenv >= lenw )
  143. du[rt] = v1, dv[rt] = v2;
  144. else
  145. du[rt] = w1, dv[rt] = w2;
  146. // printf( "du = %d, dv = %d\n", du[rt], dv[rt] );
  147. }
  148. int query( int u ) {
  149. using DSU::du;
  150. using DSU::dv;
  151. using DSU::find;
  152. int u1 = du[find(u)], u2 = dv[find(u)];
  153. return max( LCT::query(u, u1), LCT::query(u, u2) );
  154. }
  155. }
  156. int main() {
  157. type = read(), n = read(), q = read();
  158. Solve::init();
  159. while( q-- ) {
  160. if( read() == 1 ) {
  161. int u = read(), v = read();
  162. u ^= type * lastans;
  163. v ^= type * lastans;
  164. Solve::link(u, v);
  165. } else {
  166. int u = read();
  167. u ^= type * lastans;
  168. printf( "%d\n", lastans = Solve::query(u) );
  169. }
  170. }
  171. return 0;
  172. }

【题解】【雅礼集训 2017 Day5】远行 LOJ 6038 LCT的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. loj#6040. 「雅礼集训 2017 Day5」矩阵(线性代数+递推)

    题面 传送门 题解 我的线代学得跟屎一样看题解跟看天书一样所以不要指望这题我会写题解 这里 //minamoto #include<bits/stdc++.h> #define R reg ...

  8. [LOJ#6039].「雅礼集训 2017 Day5」珠宝[决策单调性]

    题意 题目链接 分析 注意到本题的 \(C\) 很小,考虑定义一个和 \(C\) 有关的状态. 记 \(f(x,j)\) 表示考虑到了价格为 \(x\) 的物品,一共花费了 \(j\) 元的最大收益. ...

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

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

随机推荐

  1. web.xml配置文件中<async-supported>true</async-supported>报错

    web.xml配置文件中<async-supported>true</async-supported>报错 http://blog.csdn.net/dream_ll/arti ...

  2. 详解HTTP缓存

    HTTP缓存是个大公司面试几乎必考的问题,写篇随笔说一下HTTP缓存. 1. HTTP报文首部中有关缓存的字段 在HTTP报文中,与缓存相关的信息都存在首部里,简单说一下首部. 首部 HTTP首部字段 ...

  3. Scrum立会报告+燃尽图(Final阶段第五次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2484 项目地址:https://coding.net/u/wuyy694 ...

  4. 软件工程第十周psp

    1.PSP表格 2.进度条 3.饼状图 4.折线图

  5. FileInputStream 读取文件数据的输入字节流

    package com.inputstream; /* File类: 用于描述一个文件或者文件夹的. 通过File对象我们可以读取文件或者文件夹的属性数据,如果我们需要读取文件的内容数据,那么我们需要 ...

  6. BNUOJ 52317 As Easy As Possible 树上倍增/主席树

    题目链接: https://acm.bnu.edu.cn/v3/problem_show.php?pid=52317 As Easy As Possible Case Time Limit: 1000 ...

  7. “吃神么,买神么”的第二个Sprint计划(总结)

    “吃神么,买神么”项目Sprint计划 ——5.28  星期四(第八天)第一次Spring计划结束   第一阶段Spring的目标以及完成情况: 时间:5月21号~5月28号(7天) 目标:第二阶段主 ...

  8. IEEE 802.11 无限局域网

    (1)无线通讯的两个重要特征 ——Hidden node problem 双方虽然听不到对方的讯号,但同时传送给相同的对象导致了碰撞(这个时候双方都不知道发生了碰撞) ——Exposed node p ...

  9. Docker基础教程

    一.Docker是什么? KVM, Virtualbox, Vmware是虚拟出机器,让每个实例看到一个单独的机器:而Docker是虚拟出操作系统,实现应用之间的隔离,让各个应用觉得自己有一个自己的操 ...

  10. 由一个滑动条的任务需求产生一个对UISlider控件的探讨

    任务需求样式: