最近学习了LinkCutTree,总结一下。

LinkCutTree是一种数据结构(是Tree Decomposition中的一种),她维护的一般是无向图(一个森林),支持连边、删边、链修改、链查询(点属于特殊的链,修改可以是单点修改、整链修改,查询可以是最值、和等)这四种操作。

中心思想是将边分类,一类边组成一些连续的链,每条链保存在一颗BST中(一般是Splay),BST中以点到根的距离为关键字(左边的点是右边的点的祖先),其它一些边连接这些链。(LinkCutTree是树链剖分(又叫轻重链剖分)的动态版本,并且更灵活),可以证明,LinkCutTree的各种操作都是均摊O(logn)的(渐进复杂度比树链剖分的O(log^2)还好,但是常数巨大,所以实测一般时间是树链剖分的1.5~2倍)。

上面的“链修改、链查询”指的是链上的点,如果要将对象改为边,可以为每条边建立一个边点,即若存在边(u,v),则新加一个点z代表边,将z连接u和v,z的点权就是(u,v)的边权,非边点的权设为-oo),然后对边权的统计就变成了对点权的统计(这是LCT中处理边信息的通法之一)。

  1 #include <cstdio>
  2 #include <iostream>
  3 #define maxn 10010
  4 using namespace std;
  5
  6 /*
  7 我的代码风格:用数组模拟指针和结构体。
  8 变量含义:
  9 pnt[u] - path-parent of u in the tree
 10 pre[u] - the father of u in the Splay
 11 son[u][0] - the left child of u in the Splay
 12 son[u][1] - the right child of u in the Splay
 13 val[u] - the weight of u
 14 sum[u] - the sum of weight of all the nodes in the subtree of u
 15 siz[u] - the number of the nodes in the subtree of u
 16 itg[u] - increasement tag ( the lazy tag )
 17 rtg[u] - rotate tag ( the lazy tag )
 18  */
 19 /*
 20 模板功能:支持删边和连边,支持将一条链的点权做一个增量,支持查询一条链的点权和,判断两点是否再同一联通块中
 21 因为是自己想的一个功能,所以没有地方交,不保证代码正确性。(重在理解)
 22 代码中哪里不懂欢迎回复,代码丑别喷。
 23 */
 24 namespace L {
 25     int pnt[maxn], pre[maxn], son[maxn][2], val[maxn],
 26         sum[maxn], siz[maxn], itg[maxn], rtg[maxn];
 27
 28     void update( int nd ) {
 29         sum[nd] = val[nd] + sum[son[nd][0]] + sum[son[nd][1]];
 30     }
 31     void rotate( int nd, int d ) {
 32         int p = pre[nd];
 33         int s = son[nd][!d];
 34         int ss = son[s][d];
 35
 36         son[nd][!d] = ss;
 37         son[s][d] = nd;
 38         if( p ) son[p][ nd==son[p][1] ] = s;
 39         else pnt[s] = pnt[nd];
 40
 41         pre[nd] = s;
 42         pre[s] = p;
 43         pre[ss] = nd;
 44
 45         update( nd );
 46         update( s );
 47     }
 48     void pushdown( int nd ) {
 49         if( rtg[nd] ) {
 50             int &ls = son[nd][0], &rs = son[nd][1];
 51             swap(ls,rs);
 52             rtg[ls] ^= 1;
 53             rtg[rs] ^= 1;
 54             rtg[nd] = 0;
 55         }
 56         if( itg[nd] ) {
 57             int ls = son[nd][0], rs = son[nd][1];
 58             int delta = itg[nd];
 59             itg[ls] += delta;
 60             itg[rs] += delta;
 61             val[ls] += delta;
 62             val[rs] += delta;
 63             sum[ls] += siz[ls]*delta;
 64             sum[rs] += siz[rs]*delta;
 65             itg[nd] = 0;
 66         }
 67     }
 68     void big_push( int nd ) {
 69         if( pre[nd] ) big_push(pre[nd]);
 70         pushdown(nd);
 71     }
 72     void splay( int nd, int top=0 ) {
 73         big_push(nd);
 74         while( pre[nd]!=top ) {
 75             int p = pre[nd];
 76             int nl = nd==son[p][0];
 77             if( pre[p]==top ) {
 78                 rotate( p, nl );
 79             } else {
 80                 int pp = pre[p];
 81                 int pl = p==son[pp][0];
 82                 if( nl==pl ) {
 83                     rotate( pp, pl );
 84                     rotate( p, nl );
 85                 } else {
 86                     rotate( p, nl );
 87                     rotate( pp, pl );
 88                 }
 89             }
 90         }
 91     }
 92     void access( int nd ) {
 93         int u = nd;
 94         int v = 0;
 95         while( u ) {
 96             splay( u );
 97             int s = son[u][1];
 98             pre[s] = 0;
 99             pnt[s] = u;
100             pre[v] = u;
101             son[u][1] = v;
102             update( u );
103             v = u;
104             u = pnt[u];
105         }
106         splay( nd );
107     }
108     int findroot( int nd ) {
109         while( pre[nd] ) nd=pre[nd];
110         while( pnt[nd] ) {
111             nd = pnt[nd];
112             while( pre[nd] ) nd=pre[nd];
113         }
114         return nd;
115     }
116     void makeroot( int nd ) {
117         access( nd );
118         rtg[nd] ^= 1;
119     }
120     bool sameroot( int u, int v ) {
121         return findroot(u)==findroot(v);
122     }
123     void link( int u, int v  ){
124         makeroot(u);
125         makeroot(v);
126         pnt[u] = v;
127     }
128     void cut( int u, int v ) {
129         makeroot(u);
130         access(v);
131         pnt[u] = 0;
132         pre[u] = 0;
133         son[v][0] = 0;
134         update( v );
135     }
136     void up_val( int u, int v, int delta ) {
137         makeroot(u);
138         access(v);
139         val[v] += delta;
140         sum[v] += siz[v]*delta;
141         itg[v] += delta;
142     }
143     int qu_sum( int u, int v ) {
144         makeroot(u);
145         access(v);
146         return val[v]+sum[son[v][0]];
147     }
148 };
149 /*
150 int main() {
151     L::link(1,2);
152     L::link(2,3);
153     L::link(3,4);
154     L::up_val(1,3,3);
155     L::up_val(2,4,-3);
156     printf( "%d\n", L::qu_sum(1,1) );
157     printf( "%d\n", L::qu_sum(2,2) );
158     printf( "%d\n", L::qu_sum(3,3) );
159     printf( "%d\n", L::qu_sum(4,4) );
160     printf( "%d\n", L::qu_sum(2,3) );
161 }
162 */
163 int main() {
164     L::link(1,2);
165     L::link(2,3);
166     L::link(3,4);
167     L::up_val( 1, 4, 5 );
168     L::cut(2,3);
169     printf( "%d\n", L::qu_sum(1,2) );
170     printf( "%d\n", L::qu_sum(3,4) );
171     printf( "%d\n", L::sameroot(2,3) );
172 }

View Code

推荐学习资料:

杨思雨 《伸展树的基本操作与应用》

杨哲 《QTREE解法的一些研究》

http://blog.csdn.net/d891320478/article/details/9181385

转载于:https://www.cnblogs.com/idy002/p/4292283.html

LinkCutTree 总结相关推荐

  1. [算法模版]Link-Cut-Tree

    [算法模版]Link-Cut-Tree 博主懒本博客只对现有博客进行补充,先直接放隔壁链接. FlashHu-LCT总结 Menci-LCT学习笔记 make-root操作 make-root操作用于 ...

  2. 【算法竞赛学习笔记】Link-Cut-Tree基础-超好懂的数据结构

    titile : Link-Cut-Tree time : 2021-7-21 tags : ACM,数据结构 author : Linno LCT Link-Cut-Tree,中文名为动态树,是一种 ...

  3. link-cut-tree 简单介绍

    目录 概念辨析 辅助树 轻边和重边 操作介绍 access make_root find_root split link cut 细节问题 代码 前言:这个算法似乎机房全都会,就我不会了TAT...强 ...

  4. LCT(link-cut-tree)入门

    ps:由于博主的qwq,把很多实边写成了实链,大家就将就着看吧嘿嘿. LCT,全称动态树,用于应付不断地加边删边的树的一种算法,非常非常优秀. 因为其经典操作link和cut而被叫做link cut ...

  5. LCT (Link-cut-tree)

    文章目录 LCT LCT定义 学习资料 四种操作 解决的问题 LCT 快退役了学一波以前听过很多次但没时间学的东西 LCT定义 学习资料 建议读论文 维基百科 https://en.wikipedia ...

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

    警告:此题不可以使用cout进行输出,只能用printf,否则RE!亲测!! 题目大意:给定一棵树,每个点有一个点权,提供四种操作: 1.删除两点之间的连边 不存在边则无视 2.在两点之前连接一条边 ...

  7. BZOJ 4025 二分图

    题目大意 给定一个\(n\)个点, \(m\)条边的无向图, 每条边在一定时间范围内存在. 要你判断每个时间点这张图是否为二分图. \(n \le 10^5\) \(m \le 2 \times 10 ...

  8. OI模板大全(普及~省选NOI)

    整理的算法模板合集: ACM模板 hhh刚从某位大佬的洛谷首页偷到了一个好玩的东西 大佬在这儿 自己对照了一下原来我还有这么多东西没有学呜呜呜我好菜 普及- 模板大全续表续表A并查集A快速幂-取余运算 ...

  9. 【ZJOI 2008】树的统计 Count

    看题目的出门左拐: http://www.zybbs.org/JudgeOnline/problem.php?id=1036 题目大意:给定一棵加权树,实现修改任意节点权值,求两点间路径最大值和权值和 ...

最新文章

  1. 谈谈“个人电子信息”的保护
  2. android使用okthtp
  3. open mpi安装
  4. stl-vector
  5. 使用graphite和grafana进行应用程序监控
  6. linux7为nginx添加服务,CentOS7添加Nginx为系统服务
  7. 异常检测机器学习_使用机器学习检测异常
  8. Linux相关配置 集群免密码登录配置
  9. 散户“大溃败”?GME连续5日暴跌80% 白银价格急转直下
  10. 你关注什么,输出什么
  11. 基于Access的学生信息管理系统设计(下):窗体设计
  12. 单词语音音标正则式查询分析JavaScript应用
  13. 改造家里的开关为智能开关,保留原有开关控制,零火版,HomeKit篇(三)
  14. JS获取当前时间的前几天、前几周、前几个月、前几年的时间
  15. 关于博客的书写——读刘末鹏博客学习方法篇有感
  16. 必备的Word软件应用技巧
  17. TI 毫米波雷达学习网站链接整理
  18. 面向对象设计的23种设计模式
  19. RISC-V 实现整数运算指令(Part 2)
  20. APP活动运营:应关注哪些数据指标?

热门文章

  1. java项目中的classpath
  2. vue --- 子组件监听点击事件,接收父组件参数.实现对应跳转
  3. javasript --- 一个日期规范(x秒前,x分前...)
  4. css --- 清除浮动
  5. Activity Monitor 闪退 无法进入睡眠
  6. 前端lvs访问多台nginx代理服务时出现404错误的处理
  7. j2ee 简单网站搭建:(十)jquery ztree 插件使用入门
  8. Zipkin-1.19.0学习系列1:java范例
  9. RGB/YUV/YCbCr--关于显示,颜色你需要了解的一些事
  10. 三星要用Exynos 9芯片打造独立VR头显