【BZOJ3626】LCA(树链剖分,Link-Cut Tree)

题面

Description

给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。

设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。

有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。

(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

Input

第一行2个整数n q。

接下来n-1行,分别表示点1到点n-1的父节点编号。

接下来q行,每行3个整数l r z。

Output

输出q行,每行表示一个询问的答案。每个答案对201314取模输出

Sample Input

5 2

0

0

1

1

1 4 3

1 4 2

Sample Output

8

5

HINT

共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

题解

我不会做的一道神题

OrzZsyDalao,看一眼就会做

如果暴力求,,,还是挺好的呀

咳咳,看正解

画画图

对于区间L~R,把每个点到根节点的路径全部+1

此时累加Z到根节点的路径权值和,发现就是答案

为啥呢

首先,我们可以知道LCA一定在Z到根节点的路径上

其次,深度就是LCA到根节点的路径长度

如果像上面那样计算,因为整个路径上都加了1

相当于加了整个LCA的深度

因此这样做就是对的

所以,直接离线处理就好了

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<set>
  8. #include<map>
  9. #include<vector>
  10. #include<queue>
  11. using namespace std;
  12. #define lson (t[x].ch[0])
  13. #define rson (t[x].ch[1])
  14. #define MAX 100000
  15. #define MOD 201314
  16. inline int read()
  17. {
  18. int x=0,t=1;char ch=getchar();
  19. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  20. if(ch=='-')t=-1,ch=getchar();
  21. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  22. return x*t;
  23. }
  24. struct Node
  25. {
  26. int ch[2],ff;
  27. int rev,pls;
  28. int size,sum,v;
  29. }t[MAX];
  30. int S[MAX],top,n,Q;
  31. bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
  32. void pushup(int x)
  33. {
  34. t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;
  35. t[x].sum=(t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+t[x].v)%MOD;
  36. }
  37. void Reverse(int x){swap(lson,rson);t[x].rev^=1;}
  38. void pushdown(int x)
  39. {
  40. if(t[x].rev)
  41. {
  42. if(lson)Reverse(lson);
  43. if(rson)Reverse(rson);
  44. t[x].rev^=1;
  45. }
  46. if(t[x].pls)
  47. {
  48. if(lson)
  49. {
  50. (t[lson].v+=t[x].pls)%=MOD;
  51. (t[lson].sum+=t[x].pls*t[lson].size%MOD)%=MOD;
  52. t[lson].pls=(t[lson].pls+t[x].pls)%MOD;
  53. }
  54. if(rson)
  55. {
  56. (t[rson].v+=t[x].pls)%=MOD;
  57. (t[rson].sum+=t[x].pls*t[rson].size%MOD)%=MOD;
  58. t[rson].pls=(t[rson].pls+t[x].pls)%MOD;
  59. }
  60. t[x].pls=0;
  61. }
  62. }
  63. void rotate(int x)
  64. {
  65. int y=t[x].ff,z=t[y].ff;
  66. int k=t[y].ch[1]==x;
  67. if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
  68. t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
  69. t[x].ch[k^1]=y;t[y].ff=x;
  70. pushup(y);pushup(x);
  71. }
  72. void Splay(int x)
  73. {
  74. S[top=1]=x;
  75. for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
  76. while(top)pushdown(S[top--]);
  77. while(!isroot(x))
  78. {
  79. int y=t[x].ff,z=t[y].ff;
  80. if(!isroot(y))
  81. (t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y);
  82. rotate(x);
  83. }
  84. }
  85. void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),t[x].ch[1]=y,pushup(x);}
  86. void makeroot(int x){access(x);Splay(x);Reverse(x);}
  87. void split(int x,int y){makeroot(x);access(y);Splay(y);}
  88. void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;pushup(y);}
  89. void link(int x,int y){makeroot(x);t[x].ff=y;}
  90. struct Ask
  91. {
  92. int id,z,i,opt;
  93. }q[MAX*2];
  94. bool cmp(Ask a,Ask b){return a.i<b.i;}
  95. int ans[MAX],tot;
  96. int main()
  97. {
  98. n=read();Q=read();
  99. for(int i=2;i<=n;++i)
  100. {
  101. int u=read()+1;
  102. link(i,u);
  103. }
  104. for(int i=1;i<=Q;++i)
  105. {
  106. int l=read(),r=read()+1,z=read()+1;
  107. ++tot;q[tot].id=q[tot+1].id=i;
  108. q[tot].z=q[tot+1].z=z;
  109. q[tot].i=l;q[tot+1].i=r;
  110. q[tot].opt=-1;q[++tot].opt=1;
  111. }
  112. sort(&q[1],&q[tot+1],cmp);
  113. int pos=1;
  114. while(!q[pos].i&&pos<tot)++pos;
  115. for(int i=1;i<=n;++i)
  116. {
  117. split(i,1);
  118. t[1].v=(t[1].v+1)%MOD;
  119. t[1].sum=(t[1].sum+t[1].size)%MOD;
  120. t[1].pls=(t[1].pls+1)%MOD;
  121. while(q[pos].i==i&&pos<=tot)
  122. {
  123. split(q[pos].z,1);
  124. ans[q[pos].id]=(ans[q[pos].id]+q[pos].opt*t[1].sum%MOD+MOD)%MOD;
  125. ++pos;
  126. }
  127. }
  128. for(int i=1;i<=Q;++i)printf("%d\n",ans[i]%MOD);
  129. return 0;
  130. }

【BZOJ3626】LCA(树链剖分,Link-Cut Tree)的更多相关文章

  1. [BZOJ3626] [LNOI2014]LCA(树链剖分)

    [BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...

  2. Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)

    Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...

  3. 【BZOJ2157】旅游(树链剖分,Link-Cut Tree)

    [BZOJ2157]旅游(树链剖分,Link-Cut Tree) 题面 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥 ...

  4. Codeforces Round #329 (Div. 2) D. Happy Tree Party LCA/树链剖分

    D. Happy Tree Party     Bogdan has a birthday today and mom gave him a tree consisting of n vertecie ...

  5. BZOJ3626[LNOI2014]LCA——树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

  6. 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

  7. [CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)

    Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花 ...

  8. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  9. 『LCA 树链剖分』

    LCA Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根 的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公 ...

随机推荐

  1. mysql 军规 (转载)

    导语 来自一线的实战经验 每一条军规背后都是血淋淋教训 不要华丽,只要实用 若有一条让你受益,慰矣 主要针对数据库开发人员 总是在灾难发生后,才想起容灾的重要性 总是在吃过亏后,才记得曾经有人提醒过 ...

  2. Hexo博客框架

    https://hexo.io/docs/#What-is-Hexo hexo博客应用1 hexo博客应用2 Spark Streaming 消费kafka到HDFS 搭建篇-使用Github-hex ...

  3. 开启MySQL远程访问权限 允许远程连接

    1.登陆mysql数据库 mysql -u root -p 查看user表 mysql> use mysql;Database changedmysql> select host,user ...

  4. MYSQL EXPLAIN执行计划命令详解(支持更新中)

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 本篇是根据官网中的每个一点来翻译.举例.验证的:英语不好,所 ...

  5. 论 Java 中的内存分配

    Java内存分配主要包括以下几个区域: 1. 寄存器:我们在程序中无法控制 2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 3. 堆:存放用new产生的数据 4. 静 ...

  6. pro asp.net mvc 5笔记

    1.Ninject条件绑定方法When(predicate)WhenClassHas<T>()WhenInj ectedInto<T>()例: kernel.Bind<I ...

  7. angular4升级angular5问题记录之No NgModule metadata found for 'AppModule'

    在将项目从angular4升级到angular5的过程中,出现No NgModule metadata found for 'AppModule'问题,网上查找答案将app.module.ts进行再次 ...

  8. POJ - 1321 dfs [kuangbin带你飞]专题一

    枚举行和列即可,当前已经放下cnt个棋子,当前已经搜索到第r行,如果 n - r + cnt  < k 直接退出,因为后面无法放下剩下的棋子. AC代码 #include<cstdio&g ...

  9. POJ1639 - Picnic Planning

    原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...

  10. 5.4 TLP中与数据负载相关的参数

    在PCIe总线中,有些TLP含有Data Payload,如存储器写请求.存储器读完成TLP等.在PCIe总线中,TLP含有的Data Payload大小与Max_Payload_Size.Max_R ...