P4211 [LNOI2014]LCA

题意

给出一个 \(n\) 个节点的有根树(编号为 \(0\) 到 \(n-1\),根节点为 \(0\))。

一个点的深度定义为这个节点到根的距离 \(+1\)。

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

有 \(m\) 次询问,每次询问给出 l r z,求 \(\sum_{i=l}^r dep[LCA(i,z)]\)。

题解

我们考虑这样一件事情,就是说,两个点的 \(Lca\) 的深度的意义到底是什么,如何才能够快速求的?

在我们不会求 \(Lca\) 的时候,我们会将一个点一个一个往上爬,并将路径上的点染色。之后我们将另一个点暴力往上跳,第一个染色过的点就是 \(Lca\)。

我们考虑到这样一件事情,如果我们将一个点到根的路径上每个点数值加 \(1\),再求得另一个点到根的路径上的权值和,这不就是 \(Lca\) 的深度了吗?

于是求解一次询问就相当于对于 \(l\le x\le r\),将 \(x\) 到根的路径上每个点加一,最后答案就是 \(z\) 到根的权值和。

由于询问次数很多,不可能每次都这样处理一遍,考虑将询问拆开。

\[\sum_{i=l}^r dep[LCA(i,z)]=\sum_{i=1}^r dep[LCA(i,z)]-\sum_{i=1}^{l-1} dep[LCA(i,z)] \]

这样我们就可以在 \(O(n\log n)\) 复杂度内解决问题啦!

这就叫数据结构二步曲,学习一下,代码我现在放下。

#define Maxn 50005
#define pb push_back
#define mod 201314
typedef long long ll;
int n,m,tot,Time,cnt;
int ans[Maxn];
int dfn[Maxn],tp[Maxn],fa[Maxn],dep[Maxn],siz[Maxn],bigson[Maxn];
int hea[Maxn],nex[Maxn],ver[Maxn];
struct TREE { int laz,sum; }tree[Maxn<<2];
struct Query { int num,z,opt; };
vector<Query> q[Maxn];
void dfs1(int x)
{siz[x]=1;for(int i=hea[x];i;i=nex[i]){fa[ver[i]]=x,dep[ver[i]]=dep[x]+1;dfs1(ver[i]),siz[x]+=siz[ver[i]];if(siz[ver[i]]>siz[bigson[x]]) bigson[x]=ver[i];}
}
void dfs2(int x,int T)
{tp[x]=T,dfn[x]=++Time;if(bigson[x]) dfs2(bigson[x],T);for(int i=hea[x];i;i=nex[i]){if(ver[i]==bigson[x]) continue;dfs2(ver[i],ver[i]);}
}
void pushdown(int p,int nl,int nr)
{int mid=(nl+nr)>>1;tree[p<<1].laz=(tree[p<<1].laz+tree[p].laz)%mod;tree[p<<1|1].laz=(tree[p<<1|1].laz+tree[p].laz)%mod;tree[p<<1].sum=(tree[p<<1].sum+1ll*tree[p].laz*(mid-nl+1)%mod)%mod;tree[p<<1|1].sum=(tree[p<<1|1].sum+1ll*tree[p].laz*(nr-mid)%mod)%mod;tree[p].laz=0;
}
void add(int p,int nl,int nr,int l,int r)
{if(nl>=l && nr<=r) { tree[p].laz++,tree[p].sum+=(nr-nl+1); return; }pushdown(p,nl,nr);int mid=(nl+nr)>>1;if(mid>=l) add(p<<1,nl,mid,l,r);if(mid<r) add(p<<1|1,mid+1,nr,l,r);tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%mod;
}
int query(int p,int nl,int nr,int l,int r)
{if(nl>=l && nr<=r) return tree[p].sum;pushdown(p,nl,nr);int mid=(nl+nr)>>1,ret=0;if(mid>=l) ret=(ret+query(p<<1,nl,mid,l,r))%mod;if(mid<r) ret=(ret+query(p<<1|1,mid+1,nr,l,r))%mod;tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%mod;return ret;
}
inline void add_path(int x)
{while(tp[x]!=tp[1]) add(1,1,n,dfn[tp[x]],dfn[x]),x=fa[tp[x]];add(1,1,n,dfn[1],dfn[x]);
}
inline int query_path(int x)
{int ret=0;while(tp[x]!=tp[1]) ret=(ret+query(1,1,n,dfn[tp[x]],dfn[x]))%mod,x=fa[tp[x]];ret=(ret+query(1,1,n,dfn[1],dfn[x]))%mod;return ret;
}
inline void add_edge(int x,int y){ ver[++tot]=y,nex[tot]=hea[x],hea[x]=tot; }
int main()
{n=rd(),m=rd();for(int i=2,f;i<=n;i++) f=rd()+1,add_edge(f,i);dfs1(1),dfs2(1,0); // 记得输入的下标从 0 开始 for(int i=1,l,r,z;i<=m;i++){l=rd()+1,r=rd()+1,z=rd()+1;q[l-1].pb((Query){i,z,-1});q[r].pb((Query){i,z,1});}for(int i=1;i<=n;i++){add_path(i);for(Query j:q[i])ans[j.num]=(ans[j.num]+j.opt*query_path(j.z)%mod+mod)%mod;}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0;
}

【做题记录】P4211 [LNOI2014]LCA相关推荐

  1. P4211 [LNOI2014]LCA(离线 + 在线 做法)

    P4211 [LNOI2014]LCA 有一棵根节点为111树,有mmm次询问,每次给定l,r,zl, r, zl,r,z,输出∑i=lrdep[lca(i,z)]\sum\limits_{i = l ...

  2. Regional 做题记录 (50/50)

    写在前面 博主深感自己太弱了QAQ 于是有了一个刷水的想法,Regional的题目还是有很多考查思维的题目,所以这次是乱做50道思考题,可能会顺带做一些水题,这些题的简要题解会写到这篇博文里面,希望能 ...

  3. 2020.7月做题记录

    转眼就到了2020的下半年了-前方仍是一片茫然. 长期计划 prufer 序列 2020.07.02-2020.07.04 Problem Finished P2624 [HNOI2008]明明的烦恼 ...

  4. 做题记录 To 2019.2.13

    2019-01-18 4543: [POI2014]Hotel加强版:长链剖分+树形dp. 3653: 谈笑风生:dfs序+主席树. POJ 3678 Katu Puzzle:2-sat问题,给n个变 ...

  5. 退役前的做题记录1.0

    退役前的做题记录1.0 租酥雨最近很懒qwq,具体表现在写题的时候不想发题解了. 但是想想这样也不太好,就决定发个一句话(半句话到几句话不等)题解上来. 2018-09.18-2018-09.28 [ ...

  6. 退役前的做题记录2.0

    退役前的做题记录2.0 最近在刷省选题......大致上是按照省份刷的. 不过上面的题目顺序是按照写题的顺序排列的,所以可能会有点乱哈. [BZOJ2823][AHOI2012]信号塔 最小圆覆盖,随 ...

  7. 概率期望题(期望 DP)做题记录

    概率期望题(期望 DP)做题记录 P3830 [SHOI2012]随机树 难点在于第二问:生成树的期望深度. 不 wei zhuo 捏,设 \(dp_{i,j}\) 表示已经有了 \(i\) 个叶子结 ...

  8. 数数题(计数类 DP)做题记录

    数数题(计数类 DP)做题记录 CF1657E Star MST 我们称张无向完全图是美丽的当且仅当:所有和 \(1\) 相连的边的边权之和等于这张完全图的最小生成树的边权之和. 完全图点数为 \(n ...

  9. CSDN 第六期编程竞赛做题记录

    CSDN 第六期编程竞赛做题记录 -- CSDN编程竞赛报名地址:https://edu.csdn.net/contest/detail/16 9.18周日闲来无视写一下 csdn 的编程题,每期编程 ...

最新文章

  1. 这次的人工智能是“有用”的人工智能
  2. Qt5.1.1 + VS2010安装错误(Unable to find a Qt build)
  3. 浅谈 iOS 版本号
  4. elastic search2.3.1(3) 查询语句拼接实战termQuery ,matchQuery, boolQuery, rangeQuery, wildcardQuery...
  5. 解析金融反欺诈技术的应用与实践
  6. PHP提取字符串中的数字
  7. Asp.net中的HttpModule和HttpHandler的简单用法
  8. [转载]创建数据库与完成数据添删改查--第一种写法
  9. 算法训练 纪念品分组(java)
  10. 【STM32】HAL库 STM32CubeMX教程十---DAC
  11. Android之深入WebView
  12. JSP中contentType和pageEncoding的区别
  13. 系统运维哪些事儿之正常状态
  14. kubernetes endpoints是什么
  15. 大学计算机基础教程第9章计算机多媒体技术
  16. 开源网络爬虫程序(spider)一览
  17. PHP中 逗号,和句号.的区别
  18. php接入支付宝app支付接口,php支付宝App支付生成预支付订单(统一下单接口)
  19. Apple iPhone 8G手机误升级至2.0降级破解日记
  20. 华为手机开启开发者模式

热门文章

  1. html 输入框自动缩短 一行内显示,JQuery UI组合框自动补全功能改进版(即时全部显示+input内容保存)...
  2. 登录服务器修改数据库吗,如何修改服务器登录数据库 sa
  3. 2021福建计算机会考操作题,2021年福建省信息技术会考笔试试题答案.doc
  4. mysql100链接同时处理_php 连接MYSQL 两个同时连接为什么只有一个连接成功,必须删掉一个,另外一个才查询生效出结果,下附代码...
  5. 还不会ts?一文带你打开ts的大门
  6. ciclop读音,购机必备,15种 3D扫描 设备 优缺点汇总
  7. java jlist 图标_java – 将图像添加到JList项目
  8. [C++11]指针空值类型nullptr
  9. 蓝桥杯2017初赛-分巧克力-二分
  10. 二叉搜索树(创建,插入,删除):基础篇,适合新手观看。