Description

给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设$dep[i]$表示点i的深度,$lca(i,j)$表示i与j的最近公共祖先。
有q次询问,每次询问给出l,r,z,求$\sum\limits_{i=l}^{r}dep[lca(i,z)]$。
(即求在$[l,r]$区间内的每个节点i与z的最近公共祖先的深度之和)

$n,q<=50000$

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

这题不算很难,但是看到正解的方法很有趣,就记录一下~

考虑暴力,每次询问把z到根的所有节点打上标记,枚举i的时候直接往根找第一个有标记的点,然后统计深度即可。

然而复杂度明显是大于$O(n^2q)$的,显然不能接受,容易发现如果把深度看成点权,那么统计深度就相当于把z到根的每个节点权值都加一,然后枚举时统计根节点到i的权值和。使用树链剖分可以降到$O(nqlog^2n)$,但是还是会超时。

考虑进一步优化,发现询问可以差分,拆成$[1,l-1]$和$[1,r]$两个询问,进一步可以发现对答案有贡献的点只会在$lca(i,z)$以上,因此把每个i到根路径上的结点权值加一,再统计z到根节点的权值和,得出的答案是相同的。再结合差分,每次直接将$[1,l-1]$或$[1,r]$中所有节点到根节点路径上的点权值加一,然后统计z到根节点的权值和,按照dfs序区间修改+区间查询,用树链剖分加线段树可以做到$O(qlog^2n)$,用LCT可以做到$O(qlogn)$

注意long long

代码:

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #define mod 201314
  7. using namespace std;
  8. typedef long long ll;
  9. struct edge{
  10. int v,next;
  11. }a[];
  12. struct task{
  13. int r,z,id,ok;
  14. }q[];
  15. int n,qq,u,v,z,tmp=,qqq=,tot=,tim=,head[],son[],siz[],fa[],dep[],dfn[],top[];
  16. ll t[],laz[],tv[],ans[],anss;
  17. bool cmp(task a,task b){
  18. return a.r<b.r;
  19. }
  20. void add(int u,int v){
  21. a[++tot].v=v;
  22. a[tot].next=head[u];
  23. head[u]=tot;
  24. }
  25. void dfs1(int u,int f,int dpt){
  26. dep[u]=dpt;
  27. fa[u]=f;
  28. siz[u]=;
  29. for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
  30. int v=a[tmp].v;
  31. if(!dep[v]){
  32. dfs1(v,u,dpt+);
  33. siz[u]+=siz[v];
  34. if(siz[v]>siz[son[u]]||son[u]==-)son[u]=v;
  35. }
  36. }
  37. }
  38. void dfs2(int u,int tp){
  39. dfn[u]=++tim;
  40. top[u]=tp;
  41. if(son[u]!=-)dfs2(son[u],tp);
  42. for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
  43. int v=a[tmp].v;
  44. if(v!=son[u])dfs2(v,v);
  45. }
  46. }
  47. void pushup(int u){
  48. t[u]=t[u*]+t[u*+];
  49. }
  50. void pushdown(int u){
  51. if(laz[u]){
  52. laz[u*]+=laz[u];
  53. laz[u*+]+=laz[u];
  54. t[u*]+=tv[u*]*laz[u];
  55. t[u*+]+=tv[u*+]*laz[u];
  56. laz[u]=;
  57. }
  58. }
  59. void build(int l,int r,int u){
  60. if(l==r){
  61. tv[u]=;
  62. return;
  63. }
  64. int mid=(l+r)/;
  65. build(l,mid,u*);
  66. build(mid+,r,u*+);
  67. tv[u]=tv[u*]+tv[u*+];
  68. }
  69. void updata(int l,int r,int u,int L,int R,int v){
  70. if(L<=l&&r<=R){
  71. t[u]+=(ll)tv[u]*v;
  72. laz[u]+=v;
  73. return;
  74. }
  75. int mid=(l+r)/;
  76. pushdown(u);
  77. if(L<=mid)updata(l,mid,u*,L,R,v);
  78. if(mid<R)updata(mid+,r,u*+,L,R,v);
  79. pushup(u);
  80. }
  81. ll query(int l,int r,int u,int L,int R){
  82. if(L<=l&&r<=R){
  83. return t[u];
  84. }
  85. int mid=(l+r)/,ans=;
  86. pushdown(u);
  87. if(L<=mid)ans+=query(l,mid,u*,L,R);
  88. if(R>mid)ans+=query(mid+,r,u*+,L,R);
  89. return ans;
  90. }
  91. void work(int u){
  92. while(u){
  93. int v=top[u];
  94. updata(,n,,dfn[v],dfn[u],);
  95. u=fa[v];
  96. }
  97. }
  98. ll _work(int u){
  99. ll ans=;
  100. while(u){
  101. int v=top[u];
  102. ans+=query(,n,,dfn[v],dfn[u]);
  103. u=fa[v];
  104. }
  105. return ans;
  106. }
  107. int main(){
  108. memset(son,-,sizeof(son));
  109. memset(head,-,sizeof(head));
  110. scanf("%d%d",&n,&qq);
  111. for(int i=;i<n;i++){
  112. scanf("%d",&u);
  113. add(u+,i+);
  114. }
  115. dfs1(,,);
  116. dfs2(,);
  117. build(,n,);
  118. for(int i=;i<=qq;i++){
  119. scanf("%d%d%d",&u,&v,&z);
  120. u++,v++,z++;
  121. q[++qqq]=(task){u-,z,i,-};
  122. q[++qqq]=(task){v,z,i,};
  123. }
  124. sort(q+,q+qqq+,cmp);
  125. for(int i=;i<=qqq;i++){
  126. while(tmp<q[i].r){
  127. work(++tmp);
  128. }
  129. ans[q[i].id]+=(ll)q[i].ok*_work(q[i].z);
  130. }
  131. for(int i=;i<=qq;i++){
  132. printf("%lld\n",ans[i]%mod);
  133. }
  134. return ;
  135. }

【LNOI2014】【BZOJ3626】NOIp2018模拟(三) LCA的更多相关文章

  1. [NOIP2018模拟赛10.16]手残报告

    [NOIP2018模拟赛10.16]手残报告 闲扯 炉石乱斗模式美滋滋啊,又颓到好晚... 上来T2先敲了树剖,看T1发现是个思博DP,然后没过大样例,写个暴力发现还是没过大样例!?才发现理解错题意了 ...

  2. JZOJ5883【NOIP2018模拟A组9.25】到不了——动态LCA裸题

    题目描述 Description wy 和 wjk 是好朋友. 今天他们在一起聊天,突然聊到了以前一起唱过的<到不了>. "说到到不了,我给你讲一个故事吧." &quo ...

  3. NOIp2018模拟赛三十六

    好久没打模拟赛了...今天一样是两道国集,一道bzoj题 成绩:13+0+95=108 A题开始看错题了...导致样例都没看懂,结果xfz提醒我后我理解了一个我自认为正确的题意(事实证明我和xfz都错 ...

  4. EZ 2018 03 09 NOIP2018 模拟赛(三)

    最近挺久没写比赛类的blog了 链接:http://211.140.156.254:2333/contest/59 这次的题目主要考验的是爆搜+打表的能力 其实如果你上来就把所有题目都看过一次就可以知 ...

  5. NOIp2018模拟赛三十八

    爆〇啦~ A题C题不会写,B题头铁写正解: 随手过拍很自信,出分一看挂成零. 若要问我为什么?gtmdsubtask! 神tm就一个subtask要么0分要么100,结果我预处理少了一点当场去世 难受 ...

  6. NOIp2018模拟赛三十七

    奇怪的一场... 前两题都是全场题,C题明显不可做,我题目都没看懂...(STO lhx OTZ) 成绩:100+100+8=208 貌似十几个208的...A题暴力$O(nmc)$能过...暴力容斥 ...

  7. NOIp2018模拟赛三十五

    两道大数据结构把我砸懵 成绩:未提交 Orz xfz两道正解 A:[BZOJ4049][CREC2014B]mountainous landscape B:CJB的大作(CF改编题)

  8. NOIp2018模拟赛三十三

    神奇的一场... 成绩:100+0+14=114 A题是个体面很恐怖的题...然而看懂题意之后转化一下就变成了一道暴力傻逼题...但是不知道为什么dalao们都没写,讲题的时候挺尴尬的...yrx“瞄 ...

  9. NOIp2018模拟赛三十二

    继续挂成傻逼 成绩:100+0+10(90)=110 A全场一眼题,C没取模挂八十分,然后没特判特殊情况又挂十分 A:[agc009b]tournament(太简单,咕了) B:[ATC2142]Bu ...

随机推荐

  1. PHP-输入账号密码进入网页

    1. 2. 3. 4.(itcast.html步骤)随便一个本地网页代替即可

  2. 由一道面试题简单扩展 — setTimeout、闭包

    在一个前端公众号,看到这么一个号称简单的面试题: 1.以下程序输出什么? <script type="text/javascript"> function init() ...

  3. Server初见——python

    import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))p ...

  4. 【转】Retina 屏幕下,网页图片的显示兼容

    感谢 Apple,带来了 Retina 屏幕的革命,让我们可以在电子显示屏上享受到印刷级的分辨率.由于分辨率的提升,网页中的文字.Flash 和 SVG 内容显示得比原来更加精细,但网页中的图片却变得 ...

  5. 😈 HTTP 学习笔记

  6. HDU 2078 选课时间( 水题 )

    链接:传送门 思路:水题略 /************************************************************************* > File N ...

  7. 2019-03-19 SQL Server简单存储过程的创建 删除 执行

    --创建名为 Get 的有输入参数的存储过程 create proc Get --设置默认值 @TrustId int ='001' as begin select * from [DealStruc ...

  8. 小学生绞尽脑汁也学不会的python(异常,约束,MD5加密,日志处理)

    小学生绞尽脑汁也学不会的python(异常,约束,MD5加密,日志处理) 异常处理(处理) 1.产生异常.raise 异常类(),抛出异常2. 处理异常: try: xxxxx # 尝试执行的代码. ...

  9. W10如何开启LinuxBash及安装Ubuntu

    W10如何开启LinuxBash的功能 1)开启开发人员模式 2)启动部分windows功能 完成后重启系统 然后在cmd中输入bash按命令操作即可使用bash命令 3)下载安装ubuntu lxr ...

  10. js常用事件及事件对象