bzoj3626 [LNOI2014]LCA——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3626
思路很巧妙,把区间换成前缀和相减;
把 l ~ r 到根路径上的点的点权都+1,然后 z 到根求和,就是 z 与 l ~ r 每个点 lca 深度的和;
这里若要用前缀和,则需要把询问离线排序;
然后上树链剖分,修改和求和线段树解决即可。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=,mod=;
int n,m,fa[maxn],head[maxn],ct,dfn[maxn],tim;
int top[maxn],to[maxn],siz[maxn],tl[maxn],tr[maxn];
struct N{
int to,next;
N(int t=,int n=):to(t),next(n) {}
}edge[maxn<<];
struct T{ll s,lzy,size;}t[maxn<<];
struct Q{int l,r,z,bh;ll ansl,ansr;}q[maxn];
void add(int x,int y){edge[++ct]=N(y,head[x]);head[x]=ct;}
bool cmp(int x,int y){return q[x].l<q[y].l;}
bool cmp2(int x,int y){return q[x].r<q[y].r;}
int rd()
{
int ret=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret;
}
void dfs(int x,int f)
{
siz[x]=;
for(int i=head[x];i;i=edge[i].next)
{
int u=edge[i].to;
if(u==f)continue;
dfs(u,x); siz[x]+=siz[u];
if(siz[u]>siz[to[x]])to[x]=u;
}
}
void dfs2(int x)
{
dfn[x]=++tim;
if(to[x])top[to[x]]=top[x],dfs2(to[x]);
for(int i=head[x];i;i=edge[i].next)
{
int u=edge[i].to;
if(u==fa[x]||u==to[x])continue;
top[u]=u; //top[u]!=x !!!
dfs2(u);
}
}
void pushup(int x)
{
t[x].size=t[x<<].size+t[x<<|].size;
t[x].s=t[x<<].s+t[x<<|].s;
}
void pushdown(int x)
{
if(!t[x].lzy)return;
int ls=(x<<),rs=(x<<|);
ll l=t[x].lzy;t[x].lzy=;
t[ls].s+=l*t[ls].size; t[ls].lzy+=l;
t[rs].s+=l*t[rs].size; t[rs].lzy+=l;
}
void build(int x,int l,int r)
{
if(l==r){t[x].size=; return;}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
void update(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
t[x].s+=t[x].size; t[x].lzy++;
return;
}
pushdown(x);
int mid=((l+r)>>);
if(mid>=L)update(x<<,l,mid,L,R);
if(mid<R)update(x<<|,mid+,r,L,R);
pushup(x);
}
void work(int x)//x 到 rt 路径上点权+1
{
while(x)
{
update(,,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
// update(1,1,n,dfn[rt],dfn[rt]);
}
ll query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x].s;
int mid=((l+r)>>); ll ret=;
pushdown(x);
if(mid>=L)ret+=query(x<<,l,mid,L,R);
if(mid<R)ret+=query(x<<|,mid+,r,L,R);
return ret;
}
ll qry(int x)
{
ll ret=;
while(x)
{
ret+=query(,,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
return ret;
}
int main()
{
n=rd();m=rd();
for(int i=;i<=n;i++){fa[i]=rd()+; add(fa[i],i); add(i,fa[i]);}
for(int i=;i<=m;i++)
{
q[i].l=rd()+; q[i].r=rd()+; q[i].z=rd()+;
tl[i]=i; tr[i]=i;
}
sort(tl+,tl+m+,cmp);
sort(tr+,tr+m+,cmp2);
dfs(,); top[]=; dfs2(); build(,,n);
int dl=,dr=;
while(q[tl[dl]].l==)dl++;
for(int i=;i<=n;i++)
{
work(i);
while(q[tl[dl]].l-==i&&dl<=m)
{
q[tl[dl]].ansl=qry(q[tl[dl]].z);//不套 dfn !!!
dl++;
}
while(q[tr[dr]].r==i&&dr<=m)
{
q[tr[dr]].ansr=qry(q[tr[dr]].z);
dr++;
}
}
for(int i=;i<=m;i++)
printf("%lld\n",(q[i].ansr-q[i].ansl)%mod);
return ;
}
bzoj3626 [LNOI2014]LCA——树链剖分的更多相关文章
- [BZOJ3626] [LNOI2014]LCA(树链剖分)
		
[BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...
 - BZOJ3626[LNOI2014]LCA——树链剖分+线段树
		
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
 - BZOJ3626 [LNOI2014]LCA 树链剖分 线段树
		
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3626 题意概括 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节 ...
 - bzoj3626: [LNOI2014]LCA (树链剖分+离线线段树)
		
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. ...
 - 【bzoj3626】[LNOI2014]LCA  树链剖分+线段树
		
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
 - BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
		
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
 - BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )
		
说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...
 - bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)
		
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...
 - BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线
		
http://www.lydsy.com/JudgeOnline/problem.php?id=3626 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...
 
随机推荐
- [codevs] 1699 开关灯
			
题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人 ...
 - 【POJ1743】Musical Theme(后缀数组,二分)
			
题意:求一个字符串的不重叠最长相同变化的子串 n<=20000 思路:这是一道论文题 我们将原串两两之间作差,可以发现所求的相同变化的子串作出的差相同 问题就转化成了不重叠的最长重复子串 显然答 ...
 - Spring mvc之SimpleUrlHandlerMapping
			
1.配置文件如下 <bean id="method" class="com.xx.controller.xxxController" scope=&quo ...
 - 偏差-方差分解Bias-Variance Decomposition
			
转自: http://www.cnblogs.com/jmp0xf/archive/2013/05/14/Bias-Variance_Decomposition.html
 - 关于Android  Service真正的全然具体解释,你须要知道的一切
			
转载请注明出处(万分感谢! ): http://blog.csdn.net/javazejian/article/details/52709857 出自[zejian的博客] Service全部内 ...
 - 【转】JavaScript错误处理和堆栈追踪
			
原文: https://www.cnblogs.com/caoru/p/6699583.html --------------------------------------------------- ...
 - composer-安装插件包
			
上一步完成后,选定国内镜像地址,以为下载插件包做准备 https://pkg.phpcomposer.com/ 安装完componser后使用下面这条命令即可(设置国内镜像地址): composer ...
 - Deepin-还原Windows平台
			
首次启动! 是不是感觉很迷茫呢? 找不到存在感 先设置成Windows那种高校模式(右键下面任意区域) OK了吧,然后我们找到“启动器”或者按Windows键(在Deepin linux我们称为Sup ...
 - C语言最小生成树prim算法(USACO3.1)
			
/* ID: hk945801 LANG: C++ TASK: agrinet */ #include<iostream> #include<cstdio> using nam ...
 - Jenkins系列之-—05 节点配置
			
一.节点配置 1. 进入[系统管理]-[节点管理]-[新建节点],录入节点名,选择Permanent Agent,下一步录入节点详细配置信息,如下: Name:节点名称 Description:节点描 ...