题面

题解

考察\(dep[\mathrm{LCA}(i, x)]\)的性质,发现它是\(i\)和\(x\)的链交的长度。

那么对每个\(i\)所在的链打一个区间加标记,询问时算一下\(x\)所在的链的区间和即可。

如果有\(l \leq i \leq r\)的限制,就进行离线处理即可。

代码

好久之前的代码,有点丑见谅。

#include<bits/stdc++.h>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define for_edge(i, x) for(RG int i=head[x];i;i=e[i].next)
#define clear(x, y) memset(x, y, sizeof(x));
using namespace std; template<typename T = int>
inline T read()
{
T data=0, w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1, ch=getchar();
while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+(ch^48), ch=getchar();
return data*w;
} const int maxn(50010), mod(201314);
struct edge { int next, to; } e[maxn];
int head[maxn], e_num, n, q;
inline void add_edge(int from, int to) { e[++e_num]={head[from], to}; head[from]=e_num; }
int fa[maxn], heavy[maxn], size[maxn];
void dfs(int x)
{
size[x]=1;
int _max=0;
for_edge(i, x)
{
int to=e[i].to; dfs(to);
size[x]+=size[to];
if(size[to]>_max) _max=size[to], heavy[x]=to;
}
}
int pos[maxn], belong[maxn], cnt_node;
void dfs(int x, int chain)
{
pos[x]=++cnt_node;
belong[x]=chain;
int k=heavy[x];
if(!k) return;
dfs(k, chain);
for_edge(i, x)
{
int to=e[i].to;
if(to==k) continue;
dfs(to, to);
}
}
int sum[maxn<<2], lazy[maxn<<2];
#define son(i) ((root<<1)|i)
inline void pushdown(int root, int l, int r)
{
if(l==r) lazy[root]=0;
if(!lazy[root]) return;
int mid(l+r>>1);
sum[son(0)]+=(mid-l+1)*lazy[root];
sum[son(1)]+=(r-mid)*lazy[root];
lazy[son(0)]+=lazy[root];
lazy[son(1)]+=lazy[root];
lazy[root]=0;
}
inline void update(int l, int r, int root=1, int nl=1, int nr=cnt_node)
{
if(nr<l || nl>r) return;
if(l<=nl && nr<=r)
{
sum[root]+=nr-nl+1;
lazy[root]++;
return;
}
int mid(nl+nr>>1);
pushdown(root, nl, nr);
update(l, r, son(0), nl, mid); update(l, r, son(1), mid+1, nr);
sum[root]=sum[son(0)]+sum[son(1)];
}
inline void update_chain(int x) { while(x) update(pos[belong[x]], pos[x]), x=fa[belong[x]]; }
inline int query(int l, int r, int root=1, int nl=1, int nr=cnt_node)
{
if(nr<l || nl>r) return 0;
if(l<=nl && nr<=r) return sum[root];
int mid(nl+nr>>1);
pushdown(root, nl, nr);
return query(l, r, son(0), nl, mid)+query(l, r, son(1), mid+1, nr);
}
inline int query_chain(int x)
{
int ans=0;
while(x) ans+=query(pos[belong[x]], pos[x]), x=fa[belong[x]];
return ans;
} vector<int> le[maxn], ri[maxn];
int ans[maxn], que[maxn];
int main()
{
n=read(); q=read();
for(RG int i=2;i<=n;i++) fa[i]=read()+1, add_edge(fa[i], i);
dfs(1); dfs(1, 1);
RG int l, r, z;
for(RG int i=1;i<=q;i++) l=read(), r=read(), z=read(), le[l].push_back(i), ri[r+1].push_back(i), que[i]=z+1;
for(RG int i=1;i<=n;i++)
{
update_chain(i);
for(RG auto j : ri[i]) (ans[j]+=query_chain(que[j]))%=mod;
for(RG auto j : le[i]) ans[j]=(ans[j]-query_chain(que[j])+mod)%mod;
}
for(RG int i=1;i<=q;i++) printf("%d\n", (ans[i]+mod)%mod);
return 0;
}

【LNOI2014】LCA的更多相关文章

  1. bzoj3626【LNOI2014】LCA

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1266  Solved: 448 [Submit][Stat ...

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

    [BZOJ3626]LCA(树链剖分,Link-Cut Tree) 题面 Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. ...

  3. 【LNOI2014】【BZOJ3626】NOIp2018模拟(三) LCA

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

  4. 【P4211 LNOI2014】LCA——树链剖分 +询问离线

    (7.16晚)更完先在B站颓一会儿-- --------------------------------------------------------------- (以下为luogu题面) 题目描 ...

  5. 【BZOJ-3626】LCA 树链剖分

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

  6. 【Homework】LCA&RMQ

    我校是神校,作业竟然选自POJ,难道不知道“珍爱生命 勿刷POJ”么? 所有注明模板题的我都十分傲娇地没有打,于是只打了6道题(其实模板题以前应该打过一部分但懒得找)(不过感觉我模板还是不够溜要找个时 ...

  7. 【模板】LCA

    代码如下 #include <bits/stdc++.h> using namespace std; const int maxn=5e5+10; inline int read(){ i ...

  8. 【BZOJ3626】LCA(树上差分,树链剖分)

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

  9. 【模板】Lca倍增法

    Codevs 1036 商务旅行 #include<cstdio> #include<cmath> #include<algorithm> using namesp ...

随机推荐

  1. MySql EF6 DBFirst 向导无法生成 edmx 解决方法(同:您的项目引用了最新实体框架;但是,找不到数据链接所需的与版本兼容的实体框架数据库提供程序)

    使用 MySql EF6 DBfirst 生成模型时经常会遇到EF6模式无法选择的情况究其原因, 还是因为没有正确的使用 Connector/Net. 下面说一下使用方法. 使用 MySql DBFi ...

  2. Oracle GI 日志收集工具 - TFA

    1.TFA的目的: TFA是个11.2版本上推出的用来收集Grid Infrastructure/RAC环境下的诊断日志的工具,它可以用非常简单的命令协助用户收集RAC里的日志,以便进一步进行诊断:T ...

  3. 转:socket

    最近浏览了几篇有关Socket发送消息的文章,发现大家对Socket Send方法理解有所偏差,现将自己在开发过程中对Socket的领悟写出来,以供大家参考. (一)架构 基于TCP协议的Socket ...

  4. Gogs集成AD域LDAP

    操作步骤: 添加认证源 使用管理员账号登录Gogs,进入控制面板→认证源管理→添加新的源 设置如图所示 使用ldap认证源登录 配置成功后,登录时可选择认真源,界面如图所示

  5. TFS使用笔记——合并不同分支的代码

    问题描述:我们需要把2.37中改动的代码合并到2.38当中. 查看“Pending Changes”,单击“Change”列排序,查看merge的items,然后选中merge的items,最后“Ch ...

  6. 函数的调用 and 打印返回值 ret= mai() print(ret)

    def mai(): # mai 函数名 (yan) 形式参数 print("老板,给我一包中华") return"给你" # 返回值-- 给你ret = ma ...

  7. 【MSSQL教程】#001 整体思维导图

    整个MSSQL体系的一个思维导图,方便理解整个MSSQL需要学习那些方面的知识.

  8. Substring Search

    查找子字符串 Introduction 在长度为 N 的文本里寻找长度为 M 的模式(子串),典型情况是 N >> M. 这个应用就很广泛啦,在文本中寻找特定的模式(子串)是很常见的需求. ...

  9. jar的解压与打包

    当我们在公司上班时候,时长需要将本地开发的作业打包上传到集群运行,由于项目过多依赖会导致jar比较庞大,因此每一次上传都比较浪费时间,为了节省时间可以使用两种办法: 1:将所有依赖一次性上传到集群上, ...

  10. 20145203JAVA课程总结

    20145203盖泽双 <Java程序设计>课程总结 课程总结 (按顺序)每周读书笔记链接汇总 调查问卷:http://www.cnblogs.com/GZSdeboke/p/524832 ...