【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】
题目链接:
题解:
可能是我比较纱布,看不懂题解,只好自己想了……
先附一个离线版本题解[Ivan]
我们考虑对于询问区间是可以差分的,然而这并没有什么卵用,然后考虑怎么统计答案。
首先LCA一定是z的祖先(这里说的祖先包括自己,以下祖先均为此概念)节点,也就是是说我们只要计算出每个祖先节点的贡献就可以了,再考虑每个祖先的贡献如何计算。
我们发现对于深度其实是该点到root的路径点数,所以我们可以这样想,我们询问z的祖先的答案,就是在计算有对于给定区间有多少个点经过了z的祖先。
那么思路到这里就很清晰了,我们先把每个点到root的路径上的点权都加1,在询问的时候用历史版本做差分即可,那么带永久化标记的主席树+树剖啊QwQ。
至于时间复杂度,有理有据的$O(nlog^2)$。
代码:
#define Troy #include <bits/stdc++.h> using namespace std; inline int read(){
int s=,k=;char ch=getchar();
while(ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while(ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
} const int N=5e4+,mod=; int n,Q; struct edges{
int v;edges *last;
}edge[N<<],*head[N];int cnt; inline void push(int u,int v){
edge[++cnt]=(edges){v,head[u]};head[u]=edge+cnt;
} class Persistent_Segment_tree{
public:
inline void add(int pos,int l,int r){
add(root[pos-],root[pos],,n,l,r);
}
inline int query(int last,int pos,int l,int r){
return query(root[last-],root[pos],,n,l,r,);
}
inline void build(){
root[]=tree;
root[]->lc=tree;
root[]->rc=tree;
cnt_tree=;
}
inline int out(){
return cnt_tree;
}
private:
struct Tree{
Tree *lc,*rc;
int sign_per,val;
Tree(){sign_per=val=;lc=rc=NULL;}
}tree[N<<],*root[N<<];int cnt_tree;
inline void add(Tree *p,Tree *&u,int l,int r,int x,int y){
u=tree+cnt_tree;cnt_tree++;
*u=*p;
u->val+=y-x+;
u->val%=mod;
if(x<=l&&r<=y){;u->sign_per++;return;}
int mid=l+r>>;
if(x>mid) add(p->rc,u->rc,mid+,r,x,y);
else if(y<=mid) add(p->lc,u->lc,l,mid,x,y);
else add(p->lc,u->lc,l,mid,x,mid),add(p->rc,u->rc,mid+,r,mid+,y);
}
inline int query(Tree *p,Tree *u,int l,int r,int x,int y,int sign_p){
if(x<=l&&r<=y){
return (sign_p*1ll*(r-l+)%mod+u->val-p->val)%+mod;
}
int mid=l+r>>,ret=;
if(y>mid) ret+=query(p->rc,u->rc,mid+,r,x,y,sign_p+u->sign_per-p->sign_per);
if(x<=mid) ret+=query(p->lc,u->lc,l,mid,x, y, sign_p+u->sign_per-p->sign_per);
return ret%;
}
}war; int fa[N],g[N],size[N],heavy[N],tid[N],idx,deep[N],L[N],R[N]; inline void dfs(int x){
size[x]=;
for(edges *i=head[x];i;i=i->last) if(i->v!=fa[x]){
deep[i->v]=deep[x]+,fa[i->v]=x,dfs(i->v);
size[x]+=size[i->v];
if(size[heavy[x]]<size[i->v])
heavy[x]=i->v;
}
} inline void dfs(int x,int grand){
tid[x]=++idx;
g[x]=grand;
if(heavy[x]){
dfs(heavy[x],grand);
for(edges *i=head[x];i;i=i->last) if(i->v!=fa[x]&&i->v!=heavy[x]){
dfs(i->v,i->v);
}
}
} inline void add(int x){
L[x]=idx+;
int t=x;
while(g[x]!=){
++idx;
war.add(idx,tid[g[x]],tid[x]);
x=fa[g[x]];
}
++idx,war.add(idx,tid[],tid[x]);
R[t]=idx;
} inline int query(int x,int l,int r){
int ret=;
while(g[x]!=){
(ret+=war.query(L[l],R[r],tid[g[x]],tid[x]))%=mod;
x=fa[g[x]];
}
ret+=war.query(L[l],R[r],tid[],tid[x]);
return ret%mod;
} int main(){
n=read(),Q=read();
for(int i=;i<=n;++i){
int x=read()+;
push(x,i),push(i,x);
}
dfs();dfs(,);idx=;
war.build();
for(int i=;i<=n;++i){
add(i);
}
while(Q--){
int l=read()+,r=read()+,z=read()+;
printf("%d\n",(query(z,l,r)%mod+mod)%mod);
}
}
【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】的更多相关文章
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- 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 离线+树链剖分
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 426 Solved: 124[Submit][Status] ...
- BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)
BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...
- [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】
题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...
- BZOJ 3626 [LNOI2014]LCA:树剖 + 差分 + 离线【将深度转化成点权之和】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626 题意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0,n <= 50 ...
- 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那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...
- BZOJ 3626: [LNOI2014]LCA(树剖+差分+线段树)
传送门 解题思路 比较有意思的一道题.首先要把求\(\sum\limits_{i=l}^r dep[lca(i,z)]\)这个公式变一下.就是考虑每一个点的贡献,做出贡献的点一定在\(z\)到根节点的 ...
随机推荐
- Python版冒泡排序算法
0 为什么写本文 一方面对经典排序算法冒泡排序进行复习,另一方面通过实际应用来检验python基础知识的掌握情况,包括range函数.len函数.for循环.if语句.函数定义与调用.列表的排序等知识 ...
- LAMP的搭建
可以在网上找整合包: httpd-2.4.18 + mysql-5.6.29 + php-5.5.30编译安装过程: 编译源代码后安装软件的位置:/usr/local/ 一.编译安装apache ap ...
- Mysql 快速指南
Mysql 快速指南 本文的示例在 Mysql 5.7 下都可以测试通过. 知识点 概念 数据库(database):保存有组织的数据的容器(通常是一个文件或一组文件). 数据表(table):某种特 ...
- J2EE--常见面试题总结 -- (二)
1 Spring拦截器的基本功能是什么? 拦截器是基于Java的反射机制的,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单 ...
- 简单而强大的bitset
简单而强大的bitset 介绍 有些程序需要处理二进制有序集,标准库提供了bitset 类型,事实上,bitset 是一个二进制容器,容器中每一个元素都是一位二进制码,或为 0,或为 1. 基础 bi ...
- 代码生成平台Xxl-Code-Generator
<代码生成平台Xxl-Code-Generator> 一.简介 1.1 概述 Xxl-Code-Generator 是一个 "controller/service/dao/myb ...
- java数据库基本操作(sqlserver 2000为例)
一.环境搭建 1.下载对应数据库连接驱动包并引入. 2.如果在web中调用必须在tomcat中也放入对应的驱动包. 3.在jre的lib\ext中也加入对应的驱动包. 二.连接数据库 public s ...
- [转]关于python中带下划线的变量和函数的意义
Python 的代码风格由 PEP 8 描述.这个文档描述了 Python 编程风格的方方面面.在遵守这个文档的条件下,不同程序员编写的 Python 代码可以保持最大程度的相似风格.这样就易于阅读, ...
- tomcat 构建问题记录
mvng构建程序包com.sun.image.codec.jpeg不存在------->缺少serlet的jar包 MasterSlaveRoutingDataSource不是抽象的, 并且未覆 ...
- Python_网络攻击之端口
#绝大多数成功的网络攻击都是以端口扫描开始的,在网络安全和黑客领域,端口扫描是经常用到的技术,可以探测指定主机上是否 #开放了指定端口,进一步判断主机是否运行了某些重要的网络服务,最终判断是否存在潜在 ...