【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\)到根节点的 ...
随机推荐
- iOS 字体权重weight
UIFontWeightUltraLight - 超细字体 UIFontWeightThin - 纤细字体 UIFontWeightLight - 亮字体 UIFontWeightRegular ...
- miniui几个常用知识点汇总
1.在表格中去除系统自带的序列号,请看代码: function allAndBrief(id) { if(id==1){ grid.set({ columns: [ { type: "ind ...
- 经典Console案例
/*下面的示例演示 WindowLeft.WindowTop.WindowWidth.WindowHeight.BufferWidth.BufferHeight 和 CursorVisible 属性以 ...
- Day15 jss整体结构梳理
JS DOM--- 两个步骤: 1 查找标签 (1)直接查找 document.getElementById("idname") // dom对象 document.getElem ...
- node七-required、缓存
学会查API,远比会几个API更重要. 核心模块意义 -如果只是在服务器运行javascript代码,并没有多大意义,因为无法实现任何功能>读写文件.访问网络 -Node的用处在于它本身还提供可 ...
- Solr(三)向solr-5.5.4中添加数据
Solr添加数据 一 首先在创建好的CORE中添加自己需要的Field(可以理解为表的字段) 1 切换到配置Field的文件目录,编辑配置Field的文件 managed-schema cd /usr ...
- mysql 存储引擎简介
几个常用存储引擎的特点 下面我们重点介绍几种常用的存储引擎并对比各个存储引擎之间的区别和推荐使用方式. 特点 Myisam BDB Memory InnoDB Archive 存储限制 没有 没有 有 ...
- 【转】asp.net获取当前页面的url地址
设当前页完整地址是:http://www.jb51.net/aaa/bbb.aspx?id=5&name=kelli "http://"是协议名 "www.jb5 ...
- Flask表单(Flask-WTF)
1.request.from获取POST表单数据 # hello.py #coding:utf-8 from flask import Flask,request,render_template ap ...
- textarea 里设置 style="resize:none"
禁止textarea拉伸的方法是:: 设置这个 style="resize:none" 属性 例子: < ...