BZOJ 3626 LCA(离线+树链剖分+差分)

显然,暴力求解的复杂度是无法承受的。
考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r
之间的点,向上搜索到第一个有标记的点求出它的深度统计答案。观察到,深度其实就是上面有几个已标记了的点(包括自身)。所以,我们不妨把 z
到根的路径上的点全部 +1,对于 l 到 r
之间的点询问他们到根路径上的点权和。仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆。也就是说我们可以对于 l 到 r 之间的点
i,将 i 到根的路径上的点全部 +1, 转而询问 z 到根的路径上的点(包括自身)的权值和就是这个询问的答案。把询问差分下,也就是用 [1,
r] − [1, l − 1] 来计算答案,那么现在我们就有一个明显的解法。从 0 到 n − 1 依次插入点 i,即将 i
到根的路径上的点全部+1。离线询问答案即可。我们现在需要一个数据结构来维护路径加和路径求和,显然树链剖分或LCT
均可以完成这个任务。树链剖分的复杂度为 O((n + q)· log n · log n),LCT的复杂度为 O((n + q)· log
n),均可以完成任务。至此,题目已经被我们完美解决。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const long long N=;
const long long mod=;
long long cnt,head[N];
long long size[N],fa[N],dep[N],son[N];
long long top[N],id[N],tot;
long long n,m,lm[N],rm[N];
struct que{
long long l,r,z;
}q[N];
struct tree{
long long l,r,sum,lazy;
}tr[N*];
vector<long long> l[N],r[N];
struct edge{
long long to,nxt;
}e[N*];
void add(long long u,long long v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs1(long long u,long long f,long long deep){
size[u]=;
fa[u]=f;
dep[u]=deep;
long long maxson=-;
for(long long i=head[u];i;i=e[i].nxt){
long long v=e[i].to;
if(v==f)continue;
dfs1(v,u,deep+);
size[u]+=size[v];
if(size[v]>maxson){
maxson=size[v];
son[u]=v;
}
}
}
void dfs2(long long u,long long tp){
top[u]=tp;
id[u]=++tot;
if(!son[u])return;
dfs2(son[u],tp);
for(long long i=head[u];i;i=e[i].nxt){
long long v=e[i].to;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
void build(long long l,long long r,long long now){
tr[now].l=l;tr[now].r=r;
if(l==r)return;
long long mid=(l+r)>>;
build(l,mid,now*);
build(mid+,r,now*+);
}
void update(long long now){
tr[now].sum=tr[now*].sum+tr[now*+].sum;
tr[now].sum%=mod;
}
void pushdown(long long now){
if(tr[now].lazy==)return;
tr[now*].sum+=((tr[now*].r-tr[now*].l+)*tr[now].lazy)%mod;
tr[now*].sum%=mod;
tr[now*+].sum+=((tr[now*+].r-tr[now*+].l+)*tr[now].lazy)%mod;
tr[now*+].sum%=mod;
tr[now*].lazy+=tr[now].lazy;
tr[now*].lazy%=mod;
tr[now*+].lazy+=tr[now].lazy;
tr[now*+].lazy%=mod;
tr[now].lazy=;
}
void change(long long l,long long r,long long now){
pushdown(now);
if(tr[now].l==l&&tr[now].r==r){
tr[now].sum+=(tr[now].r-tr[now].l+)%mod;
tr[now].sum%=mod;
tr[now].lazy+=;
return;
}
long long mid=(tr[now].l+tr[now].r)>>;
if(l>mid)change(l,r,now*+);
else if(r<=mid)change(l,r,now*);
else{
change(l,mid,now*);
change(mid+,r,now*+);
}
update(now);
}
long long getsum(long long l,long long r,long long now){
pushdown(now);
if(tr[now].l==l&&tr[now].r==r){
return tr[now].sum;
}
long long mid=(tr[now].l+tr[now].r)>>;
if(l>mid)return getsum(l,r,now*+);
else if(r<=mid)return getsum(l,r,now*);
else {
return (getsum(l,mid,now*)+getsum(mid+,r,now*+))%mod;
}
}
void changel(long long x,long long y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
change(id[top[x]],id[x],);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
change(id[x],id[y],);
}
long long getsuml(long long x,long long y){
long long ans=;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=getsum(id[top[x]],id[x],);
ans%=mod;
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans+=getsum(id[x],id[y],);
ans%=mod;
return ans;
}
int main(){
scanf("%lld%lld",&n,&m);
for(long long i=;i<=n;i++){
long long u;
scanf("%lld",&u);
add(u+,i);add(i,u+);
}
dfs1(,,);
dfs2(,);
build(,n,);
for(long long i=;i<=m;i++){
scanf("%lld%lld%lld",&q[i].l,&q[i].r,&q[i].z);
q[i].l++;q[i].r++;q[i].z++;
l[q[i].l-].push_back(i);
r[q[i].r].push_back(i);
}
for(long long i=;i<=n;i++){
changel(i,);
for(long long j=;j<l[i].size();j++){
lm[l[i][j]]=getsuml(q[l[i][j]].z,);
}
for(long long j=;j<r[i].size();j++){
rm[r[i][j]]=getsuml(q[r[i][j]].z,);
}
}
for(long long i=;i<=m;i++){
printf("%lld\n",(rm[i]-lm[i]+mod)%mod);
}
return ;
}
BZOJ 3626 LCA(离线+树链剖分+差分)的更多相关文章
- BZOJ 3626 LCA(离线+树链剖分)
首先注意到这样一个事实. 树上两个点(u,v)的LCA的深度,可以转化为先将u到根路径点权都加1,然后求v到根路径上的总点权值. 并且该题支持离线.那么我们可以把一个区间询问拆成两个前缀和形式的询问. ...
- bzoj 3626: [LNOI2014]LCA 离线+树链剖分
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 426 Solved: 124[Submit][Status] ...
- [BZOJ3626] [LNOI2014] LCA 离线 树链剖分
题面 考虑到询问的\(l..r,z\)具有可减性,考虑把询问差分掉,拆成\(r,z\)和\(l-1,z\). 显然这些LCA一定在\(z\)到根的路径上.下面的问题就是怎么统计. 考虑不是那么暴力的暴 ...
- 【BZOJ3626】[LNOI2014]LCA 离线+树链剖分+线段树
[BZOJ3626][LNOI2014]LCA Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度 ...
- 【BZOJ3626】LCA(树链剖分,Link-Cut Tree)
[BZOJ3626]LCA(树链剖分,Link-Cut Tree) 题面 Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. ...
- BZOJ 3626 离线+树链剖分+线段树
思路: 抄一波yousiki的- 显然,暴力求解的复杂度是无法承受的. 考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案 ...
- 【树链剖分 差分】bzoj3626: [LNOI2014]LCA
把LCA深度转化的那一步还是挺妙的.之后就是差分加大力数据结构了. Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep ...
- JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分
http://172.20.6.3/Problem_Show.asp?id=1454 从这道题我充分认识到我的脑子里好多水orz. 如果知道了这个要用二分和差分写,就没什么思考上的难点了(屁咧你写了一 ...
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
随机推荐
- 你不知道的JavaScript(六)Box&Unbox
很多语言中都有Box和Unbox的概念,很多书籍把Box翻译为"装箱操作",指的是將基本数据类型包装成对象:Unbox和它相反,把对象类型转换为基本类型. 我们知道JavaScri ...
- HDU 2120 Ice_cream's world I【并查集】
解题思路:给出n对点的关系,求构成多少个环,如果对于点x和点y,它们本身就有一堵墙,即为它们本身就相连,如果find(x)=find(y),说明它们的根节点相同,它们之间肯定有直接或间接的相连,即形成 ...
- js 关于height()、innerHeight()、outerHeight()函数的区别
- 为什么maven 创建web工程不自动生成Deployment Descriptor:工程名
上面图切换成下面图: 点击eclipse右上角,如下图红圈,然后在选择javaEE这样就切换成javaEE视图了 如果还是不能解决,相信这个链接对你有所帮助:https://www.cnblogs.c ...
- (转)Hadoop Eclipse开发环境搭建
来源:http://www.cnblogs.com/justinzhang/p/4261851.html This document is from my evernote, when I was s ...
- harbor 安装过程
[root@master01 harbor]# ./prepare Clearing the configuration file: ./common/config/adminserver/env ...
- rdesktop 脚本
[root@Eren liwm]# cat rdesktop.sh #!/bin/bash -rdesktop -u user 192.168.122.10 -r sound:local -g 10 ...
- 题解 UVA12206 【Stammering Aliens】
终于A了这道题啊(坑啊) 教练说:这道题不能用map吧,复杂度不一个O(nlogn)吗 于是我就一直想不出来,然后看题解代码,一看就是map... 所以我就在想,那复杂度是不是也不是O(nlogn)呢 ...
- Java基础学习总结(46)——JAVA注解快速入门
各位开发童鞋,注解这个东西我们肯定每天都能看见,也许有时候看的太多了到是会忽略注解这东西具体是如何工作的.今天在这里用最短的篇幅快速讲解下注解的原理,对这块记的不太清楚的同学也可以再次看看,下次有人详 ...
- 一个tomcat下部署多个项目或一个服务器部署多个tomcat
最近需要把两个项目同时部署到服务器上,于是研究了一下,页借鉴了很多别人的方法,把过程记录下来,以儆效尤. 目录: 1,一个tomcat下同时部署两个项目(多个项目可以参考) 1.1项目都放在webap ...