【BZOJ3626】LCA(树上差分,树链剖分)
题意:给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)
n<=50000
思路:From THU爷 LYY
我们考虑这样一种暴力:
对于dep[lca(i,j)],可以将0~i路径上的点的权值+1,那么答案就是0~j路径上的点的权值之和。
因此对于[l,r]区间,可以将每个点到根节点的权值+1,那么答案ans[l,r]就是0~z路径上的点的权值之和。
显然ans[l,r]=ans[1,r]-ans[1,l-1]。
那么可以树链剖分,然后将0~n-1这n个点插入线段树中,顺便求出答案,复杂度O(nlogn^2)。
const mo=;
var t:array[..]of record
a,s,l:longint;
end;
head,vet,next,head1,vet1,next1,c,d,
size,son,tid,id,top,flag,dep,fa,ans:array[..]of longint;
n,q,i,j,l,r,z,tot,f,v,time,e:longint; procedure add(a,b:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
head[a]:=tot;
end; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure addq(a,b,c1,d1:longint);
begin
inc(tot);
next1[tot]:=head1[a];
vet1[tot]:=b;
c[tot]:=c1;
d[tot]:=d1;
head1[a]:=tot;
end; procedure dfs1(u:longint);
var e,v,maxsize,t:longint;
begin
flag[u]:=; size[u]:=; son[u]:=; t:=;
e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
dep[v]:=dep[u]+;
dfs1(v);
size[u]:=size[u]+size[v];
if size[v]>t then
begin
t:=size[v]; son[u]:=v;
end;
e:=next[e];
end;
end;
end; procedure dfs2(u,ance:longint);
var e,v:longint;
begin
flag[u]:=; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
if son[u]> then dfs2(son[u],ance);
e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then dfs2(v,v);
e:=next[e];
end;
end; procedure hash(var x:longint);
begin
if x>=mo then x:=x mod mo;
end;
procedure pushdown(x:longint);
var l,r,tmp:longint;
begin
tmp:=t[x].a;
if tmp= then exit;
l:=x<<; r:=l+;
t[l].a:=t[l].a+tmp; hash(t[l].a);
t[r].a:=t[r].a+tmp; hash(t[r].a);
t[l].s:=t[l].s+t[l].l*tmp; hash(t[l].s);
t[r].s:=t[r].s+t[r].l*tmp; hash(t[r].s);
t[x].a:=;
end; procedure pushup(x:longint);
var l,r:longint;
begin
l:=x<<; r:=l+;
t[x].s:=t[l].s+t[r].s; hash(t[x].s);
end; procedure build(l,r,p:longint);
var mid:longint;
begin
t[p].l:=r-l+;
if l=r then exit;
mid:=(l+r)>>;
build(l,mid,p<<);
build(mid+,r,p<<+);
end; function query(l,r,x,y,p:longint):longint;
var mid:longint;
begin
if (l>=x)and(r<=y) then exit(t[p].s);
mid:=(l+r)>>;
pushdown(p);
query:=;
if x<=mid then query:=query+query(l,mid,x,y,p<<);
if y>mid then query:=query+query(mid+,r,x,y,p<<+);
// if query>=mo then query:=query-mo;
hash(query);
end; procedure update(l,r,x,y,p:longint);
var mid:longint;
begin
if (l>=x)and(r<=y) then
begin
inc(t[p].a);
// if t[p].a>=mo then t[p].a:=t[p].a-mo;
hash(t[p].a);
t[p].s:=t[p].s+t[p].l;
hash(t[p].s);
// if t[p].s>=mo then t[p].s:=t[p].s-mo;
exit;
end;
mid:=(l+r)>>;
pushdown(p);
if x<=mid then update(l,mid,x,y,p<<);
if y>mid then update(mid+,r,x,y,p<<+);
pushup(p);
end; procedure change(k:longint);
begin
while top[k]<> do
begin
update(,n,tid[top[k]],tid[k],);
k:=fa[top[k]];
end;
update(,n,,tid[k],);
end; function clac(k:longint):longint;
begin
clac:=;
while top[k]<> do
begin
clac:=clac+query(,n,tid[top[k]],tid[k],);
// if clac>=mo then clac:=clac-mo;
hash(clac);
k:=fa[top[k]];
end;
clac:=clac+query(,n,,tid[k],);
// if clac>=mo then clac:=clac-mo;
hash(clac);
end; begin
assign(input,'bzoj3626.in'); reset(input);
assign(output,'bzoj3626.out'); rewrite(output);
readln(n,q);
for i:= to n do
begin
read(fa[i]); inc(fa[i]);
add(fa[i],i);
end;
dfs1();
fillchar(flag,sizeof(flag),);
dfs2(,);
tot:=;
for i:= to q do
begin
readln(l,r,z);
inc(l); inc(r); inc(z);
addq(l-,i,z,-);
addq(r,i,z,);
end;
build(,n,);
for i:= to n do
begin
change(i);
e:=head1[i];
while e<> do
begin
v:=vet1[e]; j:=c[e]; f:=d[e];
ans[v]:=(ans[v]+f*clac(j) mod mo+mo) mod mo;
e:=next1[e];
end;
end;
for i:= to q do writeln(ans[i]); close(input);
close(output);
end.
【BZOJ3626】LCA(树上差分,树链剖分)的更多相关文章
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- 模板 树上求LCA 倍增和树链剖分
//233 模板 LCA void dfs(int x,int f){ for(int i=0;i<E[x].size();i++){ int v = E[x][i]; if(v==f)cont ...
- BZOJ 3626 LCA(离线+树链剖分+差分)
显然,暴力求解的复杂度是无法承受的. 考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案.观察到,深度其实就是上面有几个已 ...
- 培训补坑(day8:树上倍增+树链剖分)
补坑补坑.. 其实挺不理解孙爷为什么把这两个东西放在一起讲..当时我学这一块数据结构都学了一周左右吧(超虚的) 也许孙爷以为我们是省队集训班... 好吧,虽然如此,我还是会认真写博客(保证初学者不会出 ...
- bzoj4034[HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6163 Solved: 2025[Submit][Stat ...
- 洛谷P3379 【模板】最近公共祖先(LCA)(树链剖分)
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4352 Solved: 1387[Submit][Stat ...
- 4.12 省选模拟赛 LCA on tree 树链剖分 树状数组 分析答案变化量
LINK:duoxiao OJ LCA on Tree 题目: 一道树链剖分+树状数组的神题. (直接nQ的暴力有50. 其实对于树随机的时候不难想到一个算法 对于x的修改 暴力修改到根. 对于儿子的 ...
- BZOJ4034 [HAOI2015]树上操作 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4034 题意概括 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三 ...
- bzoj4034 树上操作 树链剖分+线段树
题目传送门 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有 ...
随机推荐
- 各 Android 平台版本支持的 API 级别
平台版本 API 级别 VERSION_CODE 备注 Android 7.0 24 N 平台亮点 Android 6.0 23 M 平台亮点 Android 5.1 22 LOLLIPOP_MR1 ...
- Spring-bean(一)
配置形式:基于xml文件的方式:基于注解的方式 Bean的配置方式:通过全类名(反射),通过工厂方法(静态工厂方法&实例工厂方法),FactoryBean 依赖注入的方式:属性注入,构造器注入 ...
- 【学习笔记】二:在HTML中使用JavaScript
1.<script>标签 1)考虑到最大限度的浏览器兼容性和约定俗成,type属性使用:text/javascript. 2)标签建议放置到</body>标签前,提高用户体验( ...
- ["1", "2", "3"].map(parseInt)
为什么["1", "2", "3"].map(parseInt) 为 1,NaN,NaN; parseInt() parseInt() 函数 ...
- 使用vbScript 链接SQLserver数据库和基础操作
使用vbs链接SQLserver数据库 数据库的创建.设计使用 management studio完成 1.本地链接数据库 set oCon = server.createObject("a ...
- (转)新手学习System Verilog & UVM指南
从刚接触System Verilog以及后来的VMM,OVM,UVM已经有很多年了,随着电子工业的逐步发展,国内对验证人才的需求也会急剧增加,这从各大招聘网站贴出的职位上也可以看出来,不少朋友可能想尽 ...
- 更新github上的代码
昨晚熬夜写完了"git上传本地项目代码到github"的任务,早上来公司先把早上的工作完成后,抽点时间继续来继续更新文章 更新github上的代码 一.克隆代码 1.把大神的代码c ...
- 植物大战僵尸游戏的开发(python)
装备东西: 搭建好python环境, 四张图片,(背景图片,炮弹图片,僵尸图片,豌豆图片),就ok了 没有安装pygame的需要进行安装 pip install pygame 参考视频 # 植物大 ...
- c++调用com口操作autocad
#include "stdafx.h" #include <atlcomcli.h> #import "D:\\C++test\\FirstCom\\Rele ...
- easyui实现增删改查
陈旧的开发模式 美工(ui工程师:出一个项目模型) java工程师:将原有的html转成jsp,动态展示数据 缺点: 客户需要调节前端的展示效果 解决:由美工去重新排版,重新选色. 前后端分离: 前端 ...