【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\)到根节点的 ...
随机推荐
- $("li")是对象类型不是数组类型
- parted分区详解 查看UUID两种方式 blkid 和 ls -l /dev/disk/by-uuid
通常我们用的比较多的一般都是fdisk工具来进行分区,但是现在由于磁盘越来越廉价,而且磁盘空间越来越大:而fdisk工具他对分区是有大小限制的,它只能划分小于2T的磁盘.但是现在的磁盘空间很多都已经是 ...
- nginx 反向代理,支持跨域,前后分离
前端开发往往涉及到跨域问题,其中解决方案很多: 1.jsonp 需要目标服务器配合一个callback函数. 2.window.name+iframe 需要目标服务器响应window.name. 3. ...
- Nginx日志配置及配置调试
防火墙内的内网服务器,因为网关传过来的remot_addr都一样,不得不对Nginx的日志格式做了配置 配置语法如下: log_format myformat '$http_x_forwarded ...
- Jenkins实现Android自动化打包
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/77102359 本文出自[赵彦军的博客] 1.Tomcat 进入 https://t ...
- Ocelot中文文档-配置
这里有一个配置的列子.其中有两个配置块.一个ReRoutes数组和一个GlobalConfiguration.ReRoutes配置块是一些告诉Ocelot如何处理上游请求的对象.Globalconfi ...
- 服务治理利器Hystrix-理论篇
引言 现在的大中型应用,很多都在朝着服务化.分布式的方向发展.这有多方面的考虑,比如说,方便治理.便于扩展.服务隔离等等.不过在带来如此多利好的同时,不可避免的也会带来麻烦,比如系统架构复杂.服务依赖 ...
- 关于css盒模型
在css中,width和height指的是内容区域的宽度和高度.增加内边距,边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸.假设框的每个边上有10个像素的外边距和5像素的内边距,如果希望 ...
- HTML标签fieldset
一个不常用的HTML标签fieldset,不过我觉得比较有意思,其语法如下: <fieldset> <legend>fieldset名称</legend> < ...
- 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) + 准备项目
上一部分预备知识在这 http://www.cnblogs.com/cgzl/p/9010978.html 如果您对ASP.NET Core很了解的话,可以不看本文, 本文基本都是官方文档的内容. A ...