题目链接: BZOJ - 3626

题目分析

考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就是从 y 到 Root 的路径上的点权和。

这个方法是可以叠加的,这是非常有用的一点。如果我们把 [l, r] 的每个点到 Root 的路径上所有点的权值 +1,再求出从 c 到 Root 的路径点权和,即为 [l, r] 中所有点与 c 的 LCA 的 Depth 和。

不仅满足可加性,还满足可减性,这就更好了!

那么我们就可以对每个询问 [l, r] 做一个差分,用 Query(r) - Query(l - 1) 作为答案。这样就有一种离线算法:将 n 个点依次操作,将其到 Root 的路径上的点权值 +1 ,然后如果这个点是某个询问的 l - 1 或 r ,就用那个询问的 c 求一下到 Root 的路径和,算入答案中。

Done!

写代码的时候忘记 % Mod 真是弱...

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector> using namespace std; const int MaxN = 50000 + 5, Mod = 201314; int n, m, Index;
int Father[MaxN], Depth[MaxN], Size[MaxN], Son[MaxN], Top[MaxN], Pos[MaxN];
int T[MaxN * 4], D[MaxN * 4], Len[MaxN * 4], Ans[MaxN], Q[MaxN]; vector<int> BA[MaxN], EA[MaxN]; struct Edge
{
int v;
Edge *Next;
} E[MaxN], *P = E, *Point[MaxN]; inline void AddEdge(int x, int y) {
++P; P -> v = y;
P -> Next = Point[x]; Point[x] = P;
} int DFS_1(int x, int Dep) {
Depth[x] = Dep;
Size[x] = 1;
int SonSize, MaxSonSize;
SonSize = MaxSonSize = 1;
for (Edge *j = Point[x]; j; j = j -> Next) {
SonSize = DFS_1(j -> v, Dep + 1);
if (SonSize > MaxSonSize) {
MaxSonSize = SonSize;
Son[x] = j -> v;
}
Size[x] += SonSize;
}
return Size[x];
} void DFS_2(int x) {
if (x == Son[Father[x]]) Top[x] = Top[Father[x]];
else Top[x] = x;
Pos[x] = ++Index;
if (Son[x] != 0) DFS_2(Son[x]);
for (Edge *j = Point[x]; j; j = j -> Next)
if (j -> v != Son[x]) DFS_2(j -> v);
} void Build_Tree(int x, int s, int t) {
Len[x] = t - s + 1;
D[x] = T[x] = 0;
if (s == t) return;
int m = (s + t) >> 1;
Build_Tree(x << 1, s, m);
Build_Tree(x << 1 | 1, m + 1, t);
} inline void Update(int x) {
T[x] = T[x << 1] + T[x << 1 | 1];
T[x] %= Mod;
} inline void Paint(int x, int Num) {
T[x] += Num * Len[x];
T[x] %= Mod;
D[x] += Num;
D[x] %= Mod;
} inline void PushDown(int x) {
if (D[x] == 0) return;
Paint(x << 1, D[x]);
Paint(x << 1 | 1, D[x]);
D[x] = 0;
} void Add(int x, int s, int t, int l, int r) {
if (l <= s && r >= t) {
Paint(x, 1);
return;
}
PushDown(x);
int m = (s + t) >> 1;
if (l <= m) Add(x << 1, s, m, l, r);
if (r >= m + 1) Add(x << 1 | 1, m + 1, t, l, r);
Update(x);
} void EAdd(int x) {
int fx;
fx = Top[x];
while (fx != 1) {
Add(1, 1, n, Pos[fx], Pos[x]);
x = Father[fx];
fx = Top[x];
}
Add(1, 1, n, Pos[1], Pos[x]);
} int Get(int x, int s, int t, int l, int r) {
if (l <= s && r >= t) return T[x];
int ret = 0;
PushDown(x);
int m = (s + t) >> 1;
if (l <= m) ret += Get(x << 1, s, m, l, r);
if (r >= m + 1) ret += Get(x << 1 | 1, m + 1, t, l, r);
return ret % Mod;
} int EGet(int x) {
int ret = 0, fx;
fx = Top[x];
while (fx != 1) {
ret += Get(1, 1, n, Pos[fx], Pos[x]);
ret %= Mod;
x = Father[fx];
fx = Top[x];
}
ret += Get(1, 1, n, Pos[1], Pos[x]);
return ret % Mod;
} int main()
{
scanf("%d%d", &n, &m);
int a, b, c;
for (int i = 2; i <= n; ++i) {
scanf("%d", &a);
++a;
Father[i] = a;
AddEdge(a, i);
}
DFS_1(1, 1);
Index = 0;
DFS_2(1);
Build_Tree(1, 1, n);
for (int i = 1; i <= m; ++i) {
scanf("%d%d%d", &a, &b, &c);
++a; ++b; ++c;
Q[i] = c;
BA[a - 1].push_back(i);
EA[b].push_back(i);
}
for (int i = 1; i <= n; ++i) {
EAdd(i);
for (int j = 0; j < BA[i].size(); ++j)
Ans[BA[i][j]] -= EGet(Q[BA[i][j]]);
for (int j = 0; j < EA[i].size(); ++j)
Ans[EA[i][j]] += EGet(Q[EA[i][j]]);
}
for (int i = 1; i <= m; ++i) printf("%d\n", (Ans[i] + Mod) % Mod);
return 0;
}

  

[BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】的更多相关文章

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

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

  2. BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )

    说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...

  3. BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线

    http://www.lydsy.com/JudgeOnline/problem.php?id=3626 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...

  4. bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)

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

  5. BZOJ 3626 [LNOI2014]LCA ——树链剖分

    思路转化很巧妙. 首先把询问做差分. 然后发现加入一个点就把路径上的点都+1,询问的时候直接询问到根的路径和. 这样和原问题是等价的,然后树链剖分+线段树就可以做了. #include <map ...

  6. bzoj3626: [LNOI2014]LCA (树链剖分+离线线段树)

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

  7. 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)

    题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...

  8. [LNOI2014]LCA 树链剖分 离线 前缀和 思维题

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

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

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

随机推荐

  1. Video标签播放视频?谷歌浏览器?safari?? 谷歌浏览器播放不了mp4格式的视频的原因

    webm格式和mp4格式,判断了浏览器能否支持的视频类型后,给了一个if判断,如果是支持mp4格式,就返回视频后缀mp4,如果是webm,就返回后缀webm.结果,在谷歌浏览器中播放不了,为什么我指定 ...

  2. mac下修改mysql的默认字符集为utf8

    1,检查默认安装的mysql的字符集 mysql> show variables like '%char%'; +--------------------------+------------- ...

  3. SpringMVC DispatcherServlet 说明与web配置

    使用Spring MVC,配置DispatcherServlet是第一步. DispatcherServlet是一个Servlet,所以能够配置多个DispatcherServlet. Dispatc ...

  4. cs模式与bs模式

     关于CS(Client-Server)模式和BS(Browser-Server)模式的水很深,盆地自己也认为对此了解不够透彻,但作为手机客户端设计,如果不对CS.BS做一定程度的了解,是很容易出现一 ...

  5. JS浮点类型计算

    /* ---------------- JS浮点数运算重置 ---------------- */ //加法函数 //调用:accAdd(arg1,arg2) //返回值:arg1加上arg2的精确结 ...

  6. tcp-backlog配置

    redis tcp-backlog配置   在redis2.8版本中有一个tcp-backlog配置, 说明如下: # TCP listen() backlog.## In high requests ...

  7. cocos2d源码剖析

    1. TextureAtlas http://www.cocoachina.com/bbs/read.php?tid-311439-keyword-TextureAtlas.html 2. Label ...

  8. 2进制,16进制,BCD,ascii,序列化对象相互转换

    public final static char[] BToA = "0123456789abcdef".toCharArray() ; 1.16进制字符串转为字节数组 /** * ...

  9. java.util.Random深入理解

    java.util.Random next方法的原理 比较好的参考文档: http://isky001.iteye.com/blog/1339979 package random.utilrandom ...

  10. Lambda表达式转SQL语句类库

    /* 作者:道法自然   * 个人邮件:myyangbin@sina.cn * 2014-10-1 */ Lambda表达式转SQL语句类库源码下载:http://download.csdn.net/ ...