题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626

题意:

  给出一个n个节点的有根树(编号为0到n-1,根节点为0,n <= 50000)。

  一个点的深度定义为这个节点到根的距离+1。

  设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。

  有q次询问,每次询问给出l,r,z,求∑ dep[LCA(i,z)] (l<=i<=r)。

  (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

题解:

  假设有一棵所有点都为0的树。

  如果将x到root路径上的点都+1,则dep[LCA(x,y)] = y到root路径上的点权之和,且这个操作具有叠加性。(树剖)

  所以对于询问query(l to r) = query(r) - query(l-1)。(差分)

  显然,只需要求出在询问中有的l和r的query。

  所以依次枚举节点i = 0 to n-1,将i到root的路径+1,如果i是某一些询问的l或r,则记录相应的query(z)。(离线)

  总复杂度O((n+q)*logn*logn)

AC Code:

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define MAX_N 200005
#define MAX_M 50005
#define MOD 201314 using namespace std; struct Query
{
int ver;
int id;
int dr;
Query(int _ver,int _id,int _dr)
{
ver=_ver;
id=_id;
dr=_dr;
}
Query(){};
}; int n,m;
int tot=;
int cnt=;
int l[MAX_M];
int r[MAX_M];
int z[MAX_M];
int dat[MAX_N];
int lazy[MAX_N];
int lson[MAX_N];
int rson[MAX_N];
int par[MAX_N];
int dep[MAX_N];
int siz[MAX_N];
int tp[MAX_N];
int son[MAX_N];
int dfsx[MAX_N];
int ans[MAX_M][];
vector<int> edge[MAX_N];
vector<Query> q[MAX_M]; inline int mod(int x)
{
return (x%MOD+MOD)%MOD;
} int build(int l,int r)
{
int rt=++tot;
dat[rt]=lazy[rt]=;
lson[rt]=rson[rt]=;
if(l<r)
{
int mid=(l+r)>>;
lson[rt]=build(l,mid);
rson[rt]=build(mid+,r);
}
return rt;
} void push_down(int k,int len)
{
if(lazy[k])
{
if(lson[k])
{
dat[lson[k]]=mod(dat[lson[k]]+lazy[k]*(len-(len>>)));
lazy[lson[k]]=mod(lazy[lson[k]]+lazy[k]);
}
if(rson[k])
{
dat[rson[k]]=mod(dat[rson[k]]+lazy[k]*(len>>));
lazy[rson[k]]=mod(lazy[rson[k]]+lazy[k]);
}
lazy[k]=;
}
} void push_up(int k)
{
dat[k]=;
if(lson[k]) dat[k]=mod(dat[k]+dat[lson[k]]);
if(rson[k]) dat[k]=mod(dat[k]+dat[rson[k]]);
} void update(int a,int b,int k,int l,int r,int x)
{
if(a<=l && r<=b)
{
dat[k]=mod(dat[k]+(r-l+)*x);
lazy[k]=mod(lazy[k]+x);
return;
}
if(r<a || b<l) return;
push_down(k,r-l+);
int mid=(l+r)>>;
update(a,b,lson[k],l,mid,x);
update(a,b,rson[k],mid+,r,x);
push_up(k);
} int query(int a,int b,int k,int l,int r)
{
if(a<=l && r<=b) return dat[k];
if(r<a || b<l) return ;
push_down(k,r-l+);
int mid=(l+r)>>;
int v1=query(a,b,lson[k],l,mid);
int v2=query(a,b,rson[k],mid+,r);
return mod(v1+v2);
} void dfs1(int now,int d)
{
dep[now]=d;
siz[now]=;
for(int i=;i<edge[now].size();i++)
{
int temp=edge[now][i];
if(temp!=par[now])
{
dfs1(temp,d+);
siz[now]+=siz[temp];
}
}
} void dfs2(int now,int anc)
{
tp[now]=anc;
son[now]=-;
dfsx[now]=++cnt;
for(int i=;i<edge[now].size();i++)
{
int temp=edge[now][i];
if((son[now]==- || siz[temp]>siz[son[now]]) && temp!=par[now])
{
son[now]=temp;
}
}
if(son[now]!=-) dfs2(son[now],anc);
for(int i=;i<edge[now].size();i++)
{
int temp=edge[now][i];
if(temp!=par[now] && temp!=son[now]) dfs2(temp,temp);
}
} void update_chain(int a,int x)
{
while(tp[a]!=)
{
update(dfsx[tp[a]],dfsx[a],,,n,x);
a=par[tp[a]];
}
update(,dfsx[a],,,n,x);
} int query_chain(int a)
{
int sum=;
while(tp[a]!=)
{
sum=mod(sum+query(dfsx[tp[a]],dfsx[a],,,n));
a=par[tp[a]];
}
sum=mod(sum+query(,dfsx[a],,,n));
return sum;
} void read()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
scanf("%d",&par[i]);
edge[i].push_back(par[i]);
edge[par[i]].push_back(i);
}
} void solve()
{
build(,n);
dfs1(,);
dfs2(,);
for(int i=;i<m;i++)
{
scanf("%d%d%d",&l[i],&r[i],&z[i]);
if(l[i]>) q[l[i]-].push_back(Query(z[i],i,));
q[r[i]].push_back(Query(z[i],i,));
}
memset(ans,,sizeof(ans));
for(int i=;i<n;i++)
{
update_chain(i,);
for(int j=;j<q[i].size();j++)
{
Query temp=q[i][j];
ans[temp.id][temp.dr]=query_chain(temp.ver);
}
}
} void print()
{
for(int i=;i<m;i++)
{
printf("%d\n",mod(ans[i][]-ans[i][]));
}
} int main()
{
read();
solve();
print();
}

BZOJ 3626 [LNOI2014]LCA:树剖 + 差分 + 离线【将深度转化成点权之和】的更多相关文章

  1. BZOJ 3626: [LNOI2014]LCA(树剖+差分+线段树)

    传送门 解题思路 比较有意思的一道题.首先要把求\(\sum\limits_{i=l}^r dep[lca(i,z)]\)这个公式变一下.就是考虑每一个点的贡献,做出贡献的点一定在\(z\)到根节点的 ...

  2. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  3. BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )

    说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...

  4. BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)

    BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...

  5. BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线

    http://www.lydsy.com/JudgeOnline/problem.php?id=3626 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...

  6. bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)

    Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...

  7. BZOJ 3626 [LNOI2014]LCA ——树链剖分

    思路转化很巧妙. 首先把询问做差分. 然后发现加入一个点就把路径上的点都+1,询问的时候直接询问到根的路径和. 这样和原问题是等价的,然后树链剖分+线段树就可以做了. #include <map ...

  8. bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status ...

  9. bzoj 3626: [LNOI2014]LCA 离线+树链剖分

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 426  Solved: 124[Submit][Status] ...

随机推荐

  1. Java学习第一步——JDK安装及Java环境变量配置

    Java作为当下很主流的编程语言,学习Java的朋友也越来越多了,作为一门面向对象的编程语言,Java也有着安全.高 效等诸多有点.从TIOBE(TIOBE排行榜是根据互联网上有经验的程序员.课程和第 ...

  2. 多媒体开发之---h264格式slice_header

    从Slice_Header学习H.264 写在前面: $     H.264我是结合标准和毕厚杰的书一块学的.看句法语义时最是头疼,一大堆的元素,很需要耐心.标准中在介绍某个元素的语义时,经常会突然冒 ...

  3. 查看文档的后几行命令:tail

    假如有一个文件test.txt,内容如下: [root@lee ~]# cat test.txt 这是第1行 这是第2行 这是第3行 这是第4行 这是第5行 这是第6行 这是第7行 这是第8行 这是第 ...

  4. Muduo网络库源代码分析(四)EventLoopThread和EventLoopThreadPool的封装

    muduo的并发模型为one loop per thread+ threadpool.为了方便使用,muduo封装了EventLoop和Thread为EventLoopThread,为了方便使用线程池 ...

  5. 笔试真题解析 ALBB-2015 算法project师实习生机试

    1.用十进制计算30!(30的阶乘),将结果转换成3进制进行表示的话,该进制下的结果末尾会有____个0. [解析] 计算N.下3进制结果末尾有多少个0,事实上就是计算3进制中的3被进位多少次,仅仅要 ...

  6. Android Studio 中 Gradle 依赖的统一管理(rootProjectt)

    最近遇到Android Studio 中 Gradle 依赖的统一管理的不懂得地方,看大神的也没看懂,百度了一下,使用起来还挺方便 下面是链接,在这里我就不详细说明了, http://www.jian ...

  7. python 快速排序详述

    快速排序是对“冒泡排序”的优化算法,都属于交换排序类. 描述:它通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据要小,然后再按此方法对这两部分数据分别进行快速 ...

  8. [Matlab绘图][三维图形][三维曲线基本函数+三维曲面+其他三维图形]

    1.绘制三维图形的基本函数 最基本的三维绘图函数为plot3: plot3与plot用法十分相似,调用格式: plot(x1,y1,z1,选项1,x2,y2,z2,选项2,...,xn,yn,zn,选 ...

  9. iOS UICollection 和UITableview新特性

    很详细优秀的博客: http://www.jianshu.com/p/e97780a24224 iOS10新特性总结 http://blog.csdn.net/yyacheng/article/det ...

  10. But what exactly do we mean by "gets closer to"?

    https://rdipietro.github.io/friendly-intro-to-cross-entropy-loss/ [将输入转化为输出:概率分布] When we develop a ...