【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 JoinableQueue在生产者消费者项目中的简单应用
class multiprocessing.JoinableQueue([maxsize]) JoinableQueue, a Queue subclass, is a queue which add ...
- webapi从入门到放弃(一)OWIN 自寄宿模式
1.创建web空项目 2.创建完如图 3.安装如下程序包Microsoft.AspNet.WebApi.Core (5.2.4)Microsoft.Owin.Host.SystemWeb (4.0. ...
- solr研磨之facet
作者:战斗民族就是干 转载请注明地址:http://www.cnblogs.com/prayers/p/8822417.html Facet 开门见山,facet解决的就是筛选,我是把它理解为一种聚合 ...
- $("li")是对象类型不是数组类型
- 小dai浅谈通信网络(一)——引子
说起通信网络,首先来看一个场景: 场景模式: 小明和小刚在闹市碰面. 小明对小刚大声喊道:"小刚,你好啊!" 小刚摇手答到:"你好,小明!" 就这么几句简单的话 ...
- 一个基础的for循环面试题
下面的这段程序主要考察的就是for循环的基础,输出什么?????? [html] view plaincopyprint? public class test { /** * @param args ...
- 关于Linux和Unix的分析
Linux操作系统即linux. Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.它能运行主要的UNIX工具软 ...
- OO,OO以后,及其极限
1.什么是软件开发? 软件开发的过程就是人们使用各种计算机语言将人们关心的现实世界映射到计算机世界的过程: 现在的计算机的数学理论基础是由计算机的开山鼻祖,大名鼎鼎的图灵于1937年提出的图灵机模型. ...
- 使用Navicat for MySQL把本地数据库上传到服务器
服务器系统基本都是基于linux的,这个数据库上传的方式适用于linux的各种版本,比如Ubuntu和Centos(尽管这两个版本各种大坑小坑,但至少在数据库传输上保持了一致性) 当然本地数据库上传到 ...
- Java Spring Boot 上传文件和预览文件地址解析
@RequestMapping(value ="/upload",method = RequestMethod.POST) @Permission(isAjax=false) pu ...