[bzoj3626][LNOI2014]LCA
Description
给出一个$n$个节点的有根树(编号为$0$到$n-1$,根节点为$0$)。
一个点的深度定义为这个节点到根的距离$+1$。
设$dep[i]$表示点$i$的深度,$lca(i,j)$表示$i,j$的最近公共祖先。
有$q$次询问,每次询问给出$l\;r\;z$,求$\sum_{i=l}^{r}dep[lca(i,z)]$。
(即求在$[l,r]$区间内的每个节点$i$与$z$的最近公共祖先的深度之和)
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
HINT
$n,q\;\leq\;50000$。
Solution
对于两个点$x,y$,求$dep[lca(x,y)]$,可以将$x$到根上的点全部打标记,求$y$向上第一个有标记的点的深度.
即,将$x$到根的路径上的点点权设为$1$,求$y$到根的路径权值和.
从$0$到$1$依次插入点$x$,将$x$到根的路径上的点点权$+1$.
离线处理类似前缀和的方式处理每个询问.
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 50005
#define M 201314
#define K 150005
using namespace std;
struct graph{
int nxt,to;
}e[N];
struct quest{
int x,z,n,ans;
}l[N],r[N];
struct linetree{
int l,r,s,len,lzy;
}lt[K];
int g[N],n,q,t1,t2,cnt;
int f[N],p[N],dep[N],top[N],siz[N],son[N];
inline int read(){
int ret=0;char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c)){
ret=(ret<<1)+(ret<<3)+c-'0';
c=getchar();
}
return ret;
}
inline void addedge(int x,int y){
e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
}
inline void dfs1(int u){
int m=0;siz[u]=1;
for(int i=g[u];i;i=e[i].nxt){
f[e[i].to]=u;
dep[e[i].to]=dep[u]+1;
dfs1(e[i].to);
siz[u]+=siz[e[i].to];
if(siz[e[i].to]>m){
son[u]=e[i].to;
m=siz[e[i].to];
}
}
}
inline void dfs2(int u,int tp){
top[u]=tp;p[u]=++cnt;
if(son[u]) dfs2(son[u],tp);
for(int i=g[u];i;i=e[i].nxt)
if(e[i].to!=son[u])
dfs2(e[i].to,e[i].to);
}
inline void build(int u,int l,int r){
lt[u].l=l;lt[u].r=r;lt[u].len=lt[u].r-lt[u].l+1;
if(lt[u].l<lt[u].r){
int lef=u<<1,rig=u<<1|1;
int mid=lt[u].l+lt[u].r>>1;
build(lef,l,mid);build(rig,mid+1,r);
}
}
inline int cover(int u,int l,int r){
if(lt[u].l>=l&<[u].r<=r){
++lt[u].lzy;
lt[u].s=(lt[u].s+lt[u].len)%M;
}
else if(lt[u].l<lt[u].r){
int lef=u<<1,rig=u<<1|1;
int mid=lt[u].l+lt[u].r>>1;
if(lt[u].lzy){
lt[lef].lzy+=lt[u].lzy;
lt[rig].lzy+=lt[u].lzy;
lt[lef].s=(lt[lef].s+lt[lef].len*lt[u].lzy)%M;
lt[rig].s=(lt[rig].s+lt[rig].len*lt[u].lzy)%M;
lt[u].lzy=0;
}
if(l<=mid) cover(lef,l,r);
if(r>mid) cover(rig,l,r);
lt[u].s=(lt[lef].s+lt[rig].s)%M;
}
}
inline int ask(int u,int l,int r){
if(lt[u].l>=l&<[u].r<=r)
return lt[u].s;
if(lt[u].l<lt[u].r){
int lef=u<<1,rig=u<<1|1,ret=0;
int mid=lt[u].l+lt[u].r>>1;
if(lt[u].lzy){
lt[lef].lzy+=lt[u].lzy;
lt[rig].lzy+=lt[u].lzy;
lt[lef].s=(lt[lef].s+lt[lef].len*lt[u].lzy)%M;
lt[rig].s=(lt[rig].s+lt[rig].len*lt[u].lzy)%M;
lt[u].lzy=0;
}
if(l<=mid) ret=(ret+ask(lef,l,r))%M;
if(r>mid) ret=(ret+ask(rig,l,r))%M;
return ret;
}
}
inline void add(int x,int y){
int t;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
t=x;x=y;y=t;
}
cover(1,p[top[x]],p[x]);
x=f[top[x]];
}
if(p[x]>p[y]){
t=x;x=y;y=t;
}
cover(1,p[x],p[y]);
}
inline int que(int x,int y){
int ret=0,t;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
t=x;x=y;y=t;
}
ret=(ret+ask(1,p[top[x]],p[x]))%M;
x=f[top[x]];
}
if(p[x]>p[y]){
t=x;x=y;y=t;
}
ret=(ret+ask(1,p[x],p[y]))%M;
return ret;
}
inline bool cmp1(quest x,quest y){
return x.x<y.x;
} inline bool cmp2(quest x,quest y){
return x.n<y.n;
}
inline void Aireen(){
n=read();q=read();
for(int i=2,j;i<=n;++i){
j=read()+1;addedge(j,i);
}
for(int i=1;i<=q;++i){
l[i].n=r[i].n=i;
l[i].x=read();
r[i].x=read()+1;
l[i].z=r[i].z=read()+1;
}
sort(l+1,l+1+q,cmp1);
sort(r+1,r+1+q,cmp1);
while(t1<=q&&!l[t1].x) ++t1;
while(t2<=q&&!r[t2].x) ++t2;
dep[1]=1;dfs1(1);
cnt=0;dfs2(1,1);
build(1,1,n);
for(int i=1;i<=n;++i){
add(1,i);
while(t1<=q&&l[t1].x==i){
l[t1].ans=que(1,l[t1].z);++t1;
}
while(t2<=q&&r[t2].x==i){
r[t2].ans=que(1,r[t2].z);++t2;
}
}
sort(l+1,l+1+q,cmp2);
sort(r+1,r+1+q,cmp2);
for(int i=1;i<=q;++i)
printf("%d\n",(r[i].ans-l[i].ans+M)%M);
}
int main(){
freopen("lca.in","r",stdin);
freopen("lca.out","w",stdout);
Aireen();
fclose(stdin);
fclose(stdout);
return 0;
}
[bzoj3626][LNOI2014]LCA的更多相关文章
- [BZOJ3626] [LNOI2014]LCA(树链剖分)
[BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...
- BZOJ3626 [LNOI2014]LCA 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3626 题意概括 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节 ...
- BZOJ3626[LNOI2014]LCA——树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- 2018.09.16 bzoj3626: [LNOI2014]LCA(树链剖分)
传送门 树链剖分好题. 对于每个点维护一个值vi" role="presentation" style="position: relative;"&g ...
- 【树链剖分】【线段树】bzoj3626 [LNOI2014]LCA
引用题解: http://blog.csdn.net/popoqqq/article/details/38823457 题目大意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深 ...
- bzoj3626: [LNOI2014]LCA奇技淫巧+树剖+线段树
题目求[a,b]到c的lca深度之和 显然是一个满足区间减法的操作 于是简化为 [1,b]到c的lca深度之和 (然并卵╮(╯▽╰)╭)然后就用奇技淫巧发现 a和b的lca深度=先把根节点到a的路 ...
- 【树链剖分 差分】bzoj3626: [LNOI2014]LCA
把LCA深度转化的那一步还是挺妙的.之后就是差分加大力数据结构了. Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep ...
- bzoj3626 [LNOI2014]LCA——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3626 思路很巧妙,把区间换成前缀和相减: 把 l ~ r 到根路径上的点的点权都+1,然后 ...
- BZOJ3626: [LNOI2014]LCA(树链剖分+线段树)
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...
随机推荐
- nginx php-fpm 输出php错误日志
nginx是一个web服务器,因此nginx的access日志只有对访问页面的记录,不会有php 的 error log信息. nginx把对php的请求发给php-fpm fastcgi进程来处理, ...
- linux(十二)___Apache服务器用户认证、虚拟主机的配置
创建xiangkejin zhangsan两个用户 可看见文件中创建的两个用户: 建立虚拟目录并配置用户认证 ①建立虚拟目录 /xiangkejin ②在Apache的主配置文件httpd.conf ...
- 图片的赖加载(lazyLoad)
懒加载的意义(在线demo预览) 尽管很多公司的网页都有一些限制,比如页面的最大的图片大小不得大于50k,也有很多图片优化工具fis3.gulp等等,但是如果图片太多还是会影响页面的加载速度,快则几十 ...
- SVG颜色、渐变和填充
颜色 RGB和HSL都是CSS3支持的颜色表示方法,一般普遍使用是RGB.PS:HSL浏览器兼容. RGB RGB即是代表红.绿.蓝三个通道的颜色,通过对红(R).绿(G).蓝(B)三个颜色通道的变化 ...
- [Android]Dagger2Metrics - 测量DI图表初始化的性能(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5098943.html Dagger2Metrics - 测量D ...
- Android中的 init.rc文件简介
init.rc脚本是由Android中linux的第一个用户级进程init进行解析的. init.rc 文件并不是普通的配置文件,而是由一种被称为"Android初始化语言"(An ...
- iOS10 适配问题-Xcode8
前段时间升级了Xcode8,整体来说对OC的影响不大,但是还是跳一个坑,消耗了不少时间.这里总结下遇到的适配问题. 1.权限问题 Xcode8 访问相机.相册等需要权限的地方崩溃 解决办法: 在使用私 ...
- Android应用项目中BaseAdapter、SimpleAdapter和ArrayAdapter中的三种适配器
一.写在前面: 本次我们来讲解一下Android应用中三个适配器:BaseAdapter.SimpleAdapter和ArrayAdapter.其中常见的是BaseAdapter,也是个人推荐使用的适 ...
- 初识JAVA(二)(送给Java和安卓初学者)----常见错误
博主接着上篇的来讲哦,以后的更新中,博主会出一些练习题,有兴趣的可以做做然后吧代码粘贴到下面,大家可以一起研究学习,一起进步,本篇文章主要讲的是: 一.常见错误 二.连接上篇一起的训练 无论是什么方向 ...
- Mac 开发者常用的工具
转载:http://www.oschina.net/news/53946/mac-dev-tools 在写 Mac 程序员的十个武器之前,我决定先讲一个故事,关于 Mac 和爱情的.(你们不是问 Ma ...