分析

[BZOJ3779]重组病毒唯一的区别是多了一个链上求实链段数的操作。

因为每条实链的颜色必然不相同且一条实链上不会有两个深度相同的点(好像算法的正确性和第二个条件没什么关系,算了算了),画图分析可得,如果用\(dis[x]\)表示从\(x\)到根结点路径上的实链段数,则\(x\)到\(y\)路径上的实链段数可以表示为:

\[dis[x]+dis[y]-dis[lca(x,y)]*2+1
\]

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <cctype>
  7. #include <algorithm>
  8. #define rin(i,a,b) for(int i=(a);i<=(b);i++)
  9. #define rec(i,a,b) for(int i=(a);i>=(b);i--)
  10. #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
  11. using std::cin;
  12. using std::cout;
  13. using std::endl;
  14. typedef long long LL;
  15. inline int read(){
  16. int x=0;char ch=getchar();
  17. while(ch<'0'||ch>'9') ch=getchar();
  18. while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
  19. return x;
  20. }
  21. const int MAXN=100005;
  22. int n,m;
  23. int ecnt,head[MAXN];
  24. int fa[MAXN],dep[MAXN],siz[MAXN],pc[MAXN];
  25. int top[MAXN],id[MAXN],num[MAXN],tot;
  26. int maxn[MAXN<<2],atag[MAXN<<2],loc,ql,qr,kk;
  27. int sta[MAXN],statop;
  28. struct Edge{
  29. int to,nxt;
  30. }e[MAXN<<1];
  31. inline void add_edge(int bg,int ed){
  32. ecnt++;
  33. e[ecnt].to=ed;
  34. e[ecnt].nxt=head[bg];
  35. head[bg]=ecnt;
  36. }
  37. struct lct{
  38. int fa,ch[2];
  39. int tag;
  40. }a[MAXN];
  41. inline void subupd(int x,int kkk);
  42. inline int subquery(int x);
  43. #define lc a[x].ch[0]
  44. #define rc a[x].ch[1]
  45. inline bool isroot(int x){
  46. return a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x;
  47. }
  48. inline void pushr(int x){
  49. std::swap(lc,rc);
  50. a[x].tag^=1;
  51. }
  52. inline void pushdown(int x){
  53. if(!a[x].tag) return;
  54. if(lc) pushr(lc);
  55. if(rc) pushr(rc);
  56. a[x].tag=0;
  57. }
  58. inline void rotate(int x){
  59. int y=a[x].fa,z=a[y].fa;
  60. int f=(a[y].ch[1]==x),g=a[x].ch[f^1];
  61. if(!isroot(y)) a[z].ch[a[z].ch[1]==y]=x;
  62. a[x].ch[f^1]=y;
  63. a[y].ch[f]=g;
  64. if(g) a[g].fa=y;
  65. a[y].fa=x;
  66. a[x].fa=z;
  67. }
  68. inline void splay(int x){
  69. int y=x,z;
  70. statop=1;
  71. sta[1]=y;
  72. while(!isroot(y)) sta[++statop]=y=a[y].fa;
  73. while(statop) pushdown(sta[statop--]);
  74. while(!isroot(x)){
  75. y=a[x].fa,z=a[y].fa;
  76. if(!isroot(y)){
  77. if((a[y].ch[0]==x)==(a[z].ch[0]==y)) rotate(y);
  78. else rotate(x);
  79. }
  80. rotate(x);
  81. }
  82. }
  83. inline int findroot(int x){
  84. while(pushdown(x),lc) x=lc;
  85. return x;
  86. }
  87. inline void access(int x){
  88. for(int y=0;x;x=a[y=x].fa){
  89. splay(x);
  90. if(rc) subupd(findroot(rc),1);
  91. rc=y;
  92. if(rc) subupd(findroot(rc),-1);
  93. }
  94. }
  95. #undef lc
  96. #undef rc
  97. void dfs1(int x,int pre,int depth){
  98. fa[x]=pre;
  99. a[x].fa=pre;
  100. dep[x]=depth;
  101. siz[x]=1;
  102. int maxsiz=-1;
  103. trav(i,x){
  104. int ver=e[i].to;
  105. if(ver==pre) continue;
  106. dfs1(ver,x,depth+1);
  107. siz[x]+=siz[ver];
  108. if(siz[ver]>maxsiz){
  109. maxsiz=siz[ver];
  110. pc[x]=ver;
  111. }
  112. }
  113. }
  114. void dfs2(int x,int topf){
  115. top[x]=topf;
  116. id[x]=++tot;
  117. num[tot]=x;
  118. if(!pc[x]) return;
  119. dfs2(pc[x],topf);
  120. trav(i,x){
  121. int ver=e[i].to;
  122. if(ver==fa[x]||ver==pc[x]) continue;
  123. dfs2(ver,ver);
  124. }
  125. }
  126. #define mid ((l+r)>>1)
  127. #define lc (o<<1)
  128. #define rc ((o<<1)|1)
  129. void build(int o,int l,int r){
  130. if(l==r){
  131. maxn[o]=dep[num[l]];
  132. return;
  133. }
  134. build(lc,l,mid);
  135. build(rc,mid+1,r);
  136. maxn[o]=std::max(maxn[lc],maxn[rc]);
  137. }
  138. inline void segpushdown(int o){
  139. if(!atag[o]) return;
  140. maxn[lc]+=atag[o];
  141. maxn[rc]+=atag[o];
  142. atag[lc]+=atag[o];
  143. atag[rc]+=atag[o];
  144. atag[o]=0;
  145. }
  146. void upd(int o,int l,int r){
  147. if(ql<=l&&r<=qr){
  148. maxn[o]+=kk;
  149. atag[o]+=kk;
  150. return;
  151. }
  152. segpushdown(o);
  153. if(mid>=ql) upd(lc,l,mid);
  154. if(mid<qr) upd(rc,mid+1,r);
  155. maxn[o]=std::max(maxn[lc],maxn[rc]);
  156. }
  157. int squery(int o,int l,int r){
  158. if(l==r) return maxn[o];
  159. segpushdown(o);
  160. if(loc<=mid) return squery(lc,l,mid);
  161. else return squery(rc,mid+1,r);
  162. }
  163. int rquery(int o,int l,int r){
  164. if(ql<=l&&r<=qr) return maxn[o];
  165. segpushdown(o);
  166. int ret=0;
  167. if(mid>=ql) ret=std::max(ret,rquery(lc,l,mid));
  168. if(mid<qr) ret=std::max(ret,rquery(rc,mid+1,r));
  169. return ret;
  170. }
  171. #undef mid
  172. #undef lc
  173. #undef rc
  174. inline int lca(int x,int y){
  175. while(top[x]!=top[y]){
  176. if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
  177. x=fa[top[x]];
  178. }
  179. return dep[x]<dep[y]?x:y;
  180. }
  181. inline void subupd(int x,int kkk){
  182. ql=id[x],qr=id[x]+siz[x]-1,kk=kkk;
  183. upd(1,1,n);
  184. }
  185. inline int subquery(int x){
  186. ql=id[x],qr=id[x]+siz[x]-1;
  187. return rquery(1,1,n);
  188. }
  189. int main(){
  190. n=read(),m=read();
  191. rin(i,2,n){
  192. int u=read(),v=read();
  193. add_edge(u,v);
  194. add_edge(v,u);
  195. }
  196. dfs1(1,0,1);
  197. dfs2(1,1);
  198. build(1,1,n);
  199. while(m--){
  200. int opt=read();
  201. if(opt==1){
  202. int x=read();
  203. access(x);
  204. }
  205. else if(opt==2){
  206. int ans=0;
  207. int x=read(),y=read();
  208. loc=id[x];ans+=squery(1,1,n);
  209. loc=id[y];ans+=squery(1,1,n);
  210. loc=id[lca(x,y)];ans-=(squery(1,1,n)<<1);
  211. ans++;
  212. printf("%d\n",ans);
  213. }
  214. else{
  215. int x=read();
  216. printf("%d\n",subquery(x));
  217. }
  218. }
  219. return 0;
  220. }

[BZOJ4817][SDOI2017]树点涂色:Link-Cut Tree+线段树的更多相关文章

  1. 【BZOJ4817】树点涂色(LCT,线段树,树链剖分)

    [BZOJ4817]树点涂色(LCT,线段树,树链剖分) 题面 BZOJ Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义 ...

  2. [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status ...

  3. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

  4. bzoj4817/luogu3703 树点涂色 (LCT+dfs序+线段树)

    我们发现,这个染色的操作他就很像LCT中access的操作(为什么??),然后就自然而然地想到,其实一个某条路径上的颜色数量,就是我们做一个只有access操作的LCT,这条路径经过的splay的数量 ...

  5. BZOJ.4817.[SDOI2017]树点涂色(LCT DFS序 线段树)

    题目链接 操作\(1.2\)裸树剖,但是操作\(3\)每个点的答案\(val\)很不好维护.. 如果我们把同种颜色的点划分到同一连通块中,那么向根染色的过程就是Access()! 最初所有点间都是虚边 ...

  6. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  7. Link Cut Tree 动态树 小结

    动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...

  8. LCT(link cut tree) 动态树

    模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...

  9. 洛谷.3690.[模板]Link Cut Tree(动态树)

    题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...

随机推荐

  1. Go语言入门篇-基本类型排序和 slice 排序

    参见博客:https://blog.csdn.net/u010983881/article/details/52460998 package main import ( "sort" ...

  2. Golang中的error类型

    Golang中的error类型 error类型本身就是一个预定义好的接口,里面定义了一个method type error interface { Error() string } 生成一个新的err ...

  3. centos6.9 安装mysql8

    centos6.9 安装 mysql8 # 安装mysql8 1.下载https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.16-2.el6.x86 ...

  4. [19/06/03-星期一] HTML基础_C/S与B/S的区别&标题标签(h1-h6)、段落标签(p)

    一.C/S与B/S的区别 C/S(Client/Server):客户端/服务器 1)一般使用的软件都是C/S架构,比如QQ.360.office365: 2)C表示客户端,用户通过客户端来使用软件:S ...

  5. 最全mysql笔记整理

    mysql笔记整理 作者:python技术人 博客:https://www.cnblogs.com/lpdeboke Windows服务 -- 启动MySQL net start mysql -- 创 ...

  6. es6 js数组常用方法

    一:会改变自身的方法 1.array.push(element1, ...elementN) 添加一个或多个元素到数组的末尾,并返回数组新的长度 2.array.unshift(element1, . ...

  7. 区间gcd

    http://codeforces.com/problemset/problem/914/D 题意:给你n个数,两种操作:1.询问区间[l,r]在至多一次修改一个数的条件下区间gcd是否等于x. 2. ...

  8. 不能将X*类型的值分配到X*类型的实体问题的解决方法

    今天在学习链表的过程中遇到了这个问题,我用如下方法定义了一个结构体,然后这个函数想要在链表头插入一个节点.但是在函数的最后一行却出现了报错:不能将MyLinkedList * 类型的值分配到MyLin ...

  9. HDU 2196 Computer( 树上节点的最远距离 )

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  10. 6-2 如何读写json数据

    通过查看help(json.dump)和help(json.dumps)帮助信息,dump是将转换格式到文件对象,而dumps转换格式到字符串. 一.Json.dumps() Json.dumps() ...