【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\)到根节点的 ...
随机推荐
- javascript预览图片——IT轮子系列(九)
再使用htm控件 <input type="file" name="file" /> 上传图片的时候,往往需要先预览图片,然后点击保存按钮,把图片上 ...
- 工作中EF遇到的问题
EF的条件中,无法用转格式,时间差作为条件,这时在EF6中,可以用 DbFunctions 这个类,例如: db.NewsComments.Any( (entity.PostDate - p.Pos ...
- nginx简单安装设置
1.Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄罗斯访问量第二 ...
- VirtualBox上安装64位系统
http://blog.csdn.net/mal327/article/details/6597263 原来VirtualBox安装64位的系统需要满足以下条件: 1.64位的cpu2.安装的系统必须 ...
- Linux 命令行输入
这几天刚刚接触到Linux,在windows上安装的VMWare虚拟机,Centos7.安装什么都是贾爷和办公室的同事帮忙搞定的. 在虚拟机界面,按快捷键Ctrl+Alt+Enter,可以全屏显示Li ...
- flash builder 4.6与myecilpse 10.7集成
一.在flash builder 4.0以后就没有单独提供插件版的flash builder了,因此必须先安装完整版的flash builder,再进行插件集成. 二.集成过程比较简单但也有几个要注意 ...
- Android自动化框架介绍
随着Android应用得越来越广,越来越多的公司推出了自己移动应用测试平台.例如,百度的MTC.东软易测云.Testin云测试平台…….由于自己所在项目组就是做终端测试工具的,故抽空了解了下几种常见的 ...
- System Error. Code:1722. RPC服务器不可用解决办法
原文链接(转载请注明出处):System Error. Code:1722. RPC服务器不可用解决办法 问题 最近在软件设计上机课的时候,使用 starUML 建模工具画UML图的时候总是弹出一条如 ...
- 关于 JavaScript 中的复制数组
之前在写扫雷的时候,因为需要用到二维数组,当时就在复制数组这里出现了问题,所以记录一下. 当我们在需要复制数组的时候一定需要注意,数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针, ...
- 一分钟告诉你究竟DevOps是什么鬼?
历史回顾 为了能够更好的理解什么是DevOps,我们很有必要对当时还只有程序员(此前还没有派生出开发者,前台工程师,后台工程师之类)这个称号存在的历史进行一下回顾. 如编程之道中所言: 老一辈的程序员 ...