题目链接

思路

我们换一种求\(dep[lca(i,j)]\)的方法。

将从根到\(i\)的路径上所有点的权值加\(1\),然后求从根节点到j路径上点的权值和。就是\(i\)和\(j\)的\(lca\)的深度。

以此类推,对于求\(\sum\limits_{i=l}^rdep[lca(i,z)]\),我们可以对于从l到r中的每个节点到根节点的路径上的点权值加\(1\),然后求一边从\(z\)到根节点路径和即可。这个可以用树链剖分做到。

然后再考虑多次询问。发现这个题可以离线。那就比较好处理了。

因为每次询问都是形如\([l,r]\)的形式。所以可以通过\([0,r]-[0,l-1]\)来得到\([l,r]\)的答案。所以我们对于询问离线之后,分别在每次询问的\(l-1\)和\(r\)处询问一次。相减就是答案。

代码

  1. /*
  2. * @Author: wxyww
  3. * @Date: 2019-01-29 14:50:20
  4. * @Last Modified time: 2019-01-29 16:13:25
  5. */
  6. #include<cstdio>
  7. #include<iostream>
  8. #include<cstdlib>
  9. #include<cmath>
  10. #include<ctime>
  11. #include<bitset>
  12. #include<algorithm>
  13. #include<vector>
  14. using namespace std;
  15. typedef long long ll;
  16. #define int ll
  17. const int N = 100010,mod = 201314;
  18. vector<int>e[N];
  19. ll read() {
  20. ll x=0,f=1;char c=getchar();
  21. while(c<'0'||c>'9') {
  22. if(c=='-') f=-1;
  23. c=getchar();
  24. }
  25. while(c>='0'&&c<='9') {
  26. x=x*10+c-'0';
  27. c=getchar();
  28. }
  29. return x*f;
  30. }
  31. int dep[N],top[N],son[N],dfn[N],siz[N],fa[N];
  32. void dfs1(int u,int father) {
  33. fa[u] = father;dep[u] = dep[father] + 1;siz[u] = 1;
  34. int k = e[u].size();
  35. for(int i = 0;i < k;++i) {
  36. int v = e[u][i];
  37. if(v == father) continue;
  38. dfs1(v,u);
  39. siz[u] += siz[v];
  40. if(siz[v] > siz[son[u]]) son[u] = v;
  41. }
  42. }
  43. int tot;
  44. void dfs2(int u,int father,int tt) {
  45. dfn[u] = ++tot;top[u] = tt;
  46. int k = e[u].size();
  47. if(!son[u]) return;
  48. dfs2(son[u],u,tt);
  49. for(int i = 0;i < k;++i) {
  50. int v = e[u][i];
  51. if(v == father || v == son[u]) continue;
  52. dfs2(v,u,v);
  53. }
  54. }
  55. int tree[N << 2],lazy[N << 2];
  56. void pushup(int rt) {
  57. tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1]) % mod;
  58. }
  59. void pushdown(int rt,int ln,int rn) {
  60. if(lazy[rt]) {
  61. lazy[rt << 1] += lazy[rt];
  62. lazy[rt << 1] %= mod;
  63. lazy[rt << 1 | 1] += lazy[rt];
  64. lazy[rt << 1 | 1] %= mod;
  65. tree[rt << 1] += lazy[rt] * ln;
  66. tree[rt << 1] %= mod;
  67. tree[rt << 1 | 1] += lazy[rt] * rn;
  68. tree[rt << 1 | 1] %= mod;
  69. lazy[rt] = 0;
  70. }
  71. }
  72. void update(int rt,int l,int r,int L,int R,int c) {
  73. if(L <= l && R >= r) {
  74. lazy[rt] += c;
  75. lazy[rt] %= mod;
  76. tree[rt] += c * (r - l + 1);
  77. tree[rt] %= mod;
  78. return;
  79. }
  80. int mid = (l + r) >> 1;
  81. pushdown(rt,mid - l + 1,r - mid);
  82. if(L <= mid) update(rt << 1,l,mid,L,R,c);
  83. if(R > mid) update(rt << 1 | 1,mid + 1,r,L,R,c);
  84. pushup(rt);
  85. }
  86. int query(int rt,int l,int r,int L,int R) {
  87. if(L <= l && R >= r)
  88. return tree[rt];
  89. int mid = (l + r) >> 1;
  90. pushdown(rt,mid - l + 1,r - mid);
  91. int ans = 0;
  92. if(L <= mid) ans += query(rt << 1,l,mid,L,R),ans %= mod;
  93. if(R > mid) ans += query(rt << 1 | 1,mid + 1,r,L,R),ans %= mod;
  94. return ans;
  95. }
  96. void UPDATE(int rt,int c) {
  97. while(rt != 0) {
  98. update(1,1,tot,dfn[top[rt]],dfn[rt],c);
  99. rt = fa[top[rt]];
  100. }
  101. }
  102. int Query(int rt) {
  103. int ans = 0;
  104. while(rt != 0) {
  105. ans += query(1,1,tot,dfn[top[rt]],dfn[rt]);
  106. ans %= mod;
  107. rt = fa[top[rt]];
  108. }
  109. return ans;
  110. }
  111. struct node {
  112. int id,z,x,ans;
  113. }ask[N];
  114. bool cmp(node x,node y) {
  115. return x.x < y.x;
  116. }
  117. bool cmp2(node x,node y) {
  118. return x.id < y.id;
  119. }
  120. int js;
  121. signed main() {
  122. int n = read(),Q = read();
  123. for(int i = 2;i <= n;++i) {
  124. int x = read() + 1;
  125. e[i].push_back(x);e[x].push_back(i);
  126. }
  127. for(int i = 1;i <= Q;++i) {
  128. int l = read() + 1,r = read() + 1,z = read() + 1;
  129. ask[++js].id = js;
  130. ask[js].x = l - 1;ask[js].z = z;
  131. ask[++js].id = js;
  132. ask[js].x = r;ask[js].z = z;
  133. }
  134. dfs1(1,0);
  135. dfs2(1,0,1);
  136. sort(ask + 1,ask + js + 1,cmp);
  137. int now = 1;
  138. while(ask[now].x == 0) ++now;
  139. for(int i = 1;i <= n;++i) {
  140. UPDATE(i,1);
  141. while(ask[now].x == i) {
  142. ask[now].ans = Query(ask[now].z);
  143. ++now;
  144. }
  145. }
  146. sort(ask + 1,ask + js + 1,cmp2);
  147. for(int i = 2;i <= js;i += 2)
  148. printf("%lld\n",(ask[i].ans - ask[i - 1].ans + mod) % mod);
  149. return 0;
  150. }

luogu4211 LCA的更多相关文章

  1. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  2. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  3. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  4. [bzoj2588][count on a tree] (主席树+lca)

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

  5. [板子]倍增LCA

    倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...

  6. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  7. [bzoj3626][LNOI2014]LCA

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

  8. (RMQ版)LCA注意要点

    inline int lca(int x,int y){ if(x>y) swap(x,y); ]][x]]<h[rmq[log[y-x+]][y-near[y-x+]+]])? rmq[ ...

  9. bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)

    题目大意:一棵树,以一定顺序走完n个点,求每个点经过多少遍 可以树链剖分,也可以直接在树上做差分序列的标记 后者打起来更舒适一点.. 具体实现: 先求x,y的lca,且dep[x]<dep[y] ...

随机推荐

  1. hive安装详解

    1.安装MYSQL simon@simon-Lenovo-G400:~$ sudo apt-get install mysql-server simon@simon-Lenovo-G400:~$ su ...

  2. 重写TreeView模板来实现数据分层展示(二)

    前面一片文章实现TreeView的基本的模板重写,那么照着这个思路,我们再来写一个稍稍复杂的TreeView ,其它的内容都和前面系列内容相似,还是和之前文章介绍的一样,首先看看做出的DEMO的最终样 ...

  3. DAY04、流程控制if、while、for

    一.if 判断 语法一: if 条件: # 以下是上一条if 的子代码块 print(子代码1) print(子代码2) print(子代码3) 示例: # 路边飘过一个生物,要不要表白? sex = ...

  4. SSH的使用

    1.如何设置SSH的超时时间 使用SSH客户端软件登录linux服务器后,执行 echo $TMOUT可以查看SSH链接超时时间: 使用vim /etc/profile可以编辑配置页面 修改TMOUT ...

  5. 《Tensorflow从入门到精通》

    第一 开发环境搭建 1. tensorflow的环境搭建 windows下安装cpu版tensorflow: pip install tensorflow 在ubuntu上安装gpu版tensorfl ...

  6. js一元运算符

    否运算符(按位非):~    加1取反 console.log(~-); console.log(~-); console.log(~); //-1 void():计算表达式,但是不返回值(仅仅是不返 ...

  7. How to hosts

    sudo cp /etc/hosts /etc/hosts.bak sudo cp ~/Desktop/hosts /etc/hosts sudo systemctl restart NetworkM ...

  8. hdu-1358(kmp)

    题意:给你一个长度为n的字符串,问你一共有多少Xi——从0开始到Xi的这段长度这个字符子串是循环串,并输出最多的循环节的次数: 解题思路:用kmp的next数组,我们从next数组的值中可以看出这个字 ...

  9. CodeForces 589B-Layer Cake-暴力模拟

    刚看到这个题的想法是建图搜路,写出来了才发现这个做法不行,不能把每一个矩形看成不可分的点,因为最终的矩形可能两条边出现在不同矩形里. 后来看了题解才明白直接暴力就行.关键是明白最终的矩形两条边都在所给 ...

  10. CodeForces615A-Bulbs-模拟

    水题 #include <cstdio> #include <algorithm> using namespace std; ]; int main() { scanf(&qu ...