bzoj3626 [LNOI2014]LCA——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3626
思路很巧妙,把区间换成前缀和相减;
把 l ~ r 到根路径上的点的点权都+1,然后 z 到根求和,就是 z 与 l ~ r 每个点 lca 深度的和;
这里若要用前缀和,则需要把询问离线排序;
然后上树链剖分,修改和求和线段树解决即可。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=,mod=;
int n,m,fa[maxn],head[maxn],ct,dfn[maxn],tim;
int top[maxn],to[maxn],siz[maxn],tl[maxn],tr[maxn];
struct N{
int to,next;
N(int t=,int n=):to(t),next(n) {}
}edge[maxn<<];
struct T{ll s,lzy,size;}t[maxn<<];
struct Q{int l,r,z,bh;ll ansl,ansr;}q[maxn];
void add(int x,int y){edge[++ct]=N(y,head[x]);head[x]=ct;}
bool cmp(int x,int y){return q[x].l<q[y].l;}
bool cmp2(int x,int y){return q[x].r<q[y].r;}
int rd()
{
int ret=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret;
}
void dfs(int x,int f)
{
siz[x]=;
for(int i=head[x];i;i=edge[i].next)
{
int u=edge[i].to;
if(u==f)continue;
dfs(u,x); siz[x]+=siz[u];
if(siz[u]>siz[to[x]])to[x]=u;
}
}
void dfs2(int x)
{
dfn[x]=++tim;
if(to[x])top[to[x]]=top[x],dfs2(to[x]);
for(int i=head[x];i;i=edge[i].next)
{
int u=edge[i].to;
if(u==fa[x]||u==to[x])continue;
top[u]=u; //top[u]!=x !!!
dfs2(u);
}
}
void pushup(int x)
{
t[x].size=t[x<<].size+t[x<<|].size;
t[x].s=t[x<<].s+t[x<<|].s;
}
void pushdown(int x)
{
if(!t[x].lzy)return;
int ls=(x<<),rs=(x<<|);
ll l=t[x].lzy;t[x].lzy=;
t[ls].s+=l*t[ls].size; t[ls].lzy+=l;
t[rs].s+=l*t[rs].size; t[rs].lzy+=l;
}
void build(int x,int l,int r)
{
if(l==r){t[x].size=; return;}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
void update(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
t[x].s+=t[x].size; t[x].lzy++;
return;
}
pushdown(x);
int mid=((l+r)>>);
if(mid>=L)update(x<<,l,mid,L,R);
if(mid<R)update(x<<|,mid+,r,L,R);
pushup(x);
}
void work(int x)//x 到 rt 路径上点权+1
{
while(x)
{
update(,,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
// update(1,1,n,dfn[rt],dfn[rt]);
}
ll query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x].s;
int mid=((l+r)>>); ll ret=;
pushdown(x);
if(mid>=L)ret+=query(x<<,l,mid,L,R);
if(mid<R)ret+=query(x<<|,mid+,r,L,R);
return ret;
}
ll qry(int x)
{
ll ret=;
while(x)
{
ret+=query(,,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
return ret;
}
int main()
{
n=rd();m=rd();
for(int i=;i<=n;i++){fa[i]=rd()+; add(fa[i],i); add(i,fa[i]);}
for(int i=;i<=m;i++)
{
q[i].l=rd()+; q[i].r=rd()+; q[i].z=rd()+;
tl[i]=i; tr[i]=i;
}
sort(tl+,tl+m+,cmp);
sort(tr+,tr+m+,cmp2);
dfs(,); top[]=; dfs2(); build(,,n);
int dl=,dr=;
while(q[tl[dl]].l==)dl++;
for(int i=;i<=n;i++)
{
work(i);
while(q[tl[dl]].l-==i&&dl<=m)
{
q[tl[dl]].ansl=qry(q[tl[dl]].z);//不套 dfn !!!
dl++;
}
while(q[tr[dr]].r==i&&dr<=m)
{
q[tr[dr]].ansr=qry(q[tr[dr]].z);
dr++;
}
}
for(int i=;i<=m;i++)
printf("%lld\n",(q[i].ansr-q[i].ansl)%mod);
return ;
}
bzoj3626 [LNOI2014]LCA——树链剖分的更多相关文章
- [BZOJ3626] [LNOI2014]LCA(树链剖分)
[BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...
- BZOJ3626[LNOI2014]LCA——树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- BZOJ3626 [LNOI2014]LCA 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3626 题意概括 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节 ...
- bzoj3626: [LNOI2014]LCA (树链剖分+离线线段树)
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. ...
- 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- 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 (树链剖分+线段树)
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那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...
随机推荐
- 舆论的力量---数学建模初探(SI模型)
在高中时除了物理竞赛没有学习外,竞赛的五大学科剩下的四门均有所涉猎及参加,因而精力分散太多.因此下定决心大学时可以广泛涉猎知识,但是主攻的竞赛只能有两个ACM和MCM,如今虽然高考完挂,但学术之心尚存 ...
- 【板+背包】多重背包 HDU Coins
http://acm.hdu.edu.cn/showproblem.php?pid=2844 [题意] 给定n种价值为Ci,个数为Wi的硬币,问在1~V中的这些数中哪些数能由这些硬币组成? [思路] ...
- rest-assured(一)报错解决方案
1.javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? --------1.端口设置错误 ----- ...
- hihoCoder #1014 : Trie树 [ Trie ]
传送门 #1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互 ...
- Method, apparatus and system for acquiring a global promotion facility utilizing a data-less transaction
A data processing system includes a global promotion facility and a plurality of processors coupled ...
- HDU 1028 整数拆分 HDU 2082 找单词 母函数
生成函数(母函数) 母函数又称生成函数.定义是给出序列:a0,a1,a2,...ak,...an, 那么函数G(x)=a0+a1*x+a2*x2+....+ak*xk +...+an* xn 称为序 ...
- UVA 10200 Prime Time【暴力,精度】
题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_proble ...
- P1195 口袋的天空 洛谷
https://www.luogu.org/problem/show?pid=1195 题目背景 小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空. 有很多云飘在那里,看起来很漂亮,小杉想摘下那样美 ...
- SpringDataJPA入门2
SpringDataJPA实体概述 JPA提供了一种简单高效的方式来管理Java对象(POJO)到关系型数据库的映射,此类Java对象成为JPA实体或简称实体.实体通常与底层数据库中的单个关系表相关联 ...
- pip命令自动补全功能;设置代理;使用国内源
这是pip自带的功能 执行的脚本 把脚本写入.zshrc或者profile等里面,执行source立即生效 设置代理: pip --proxy=http://username:password@pro ...