题目描述

给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。 有q次询问,每次询问给出l r z,求 ∑l<=i<=r dep[LCA(i,z)]

输入输出格式

输入格式:

第一行2个整数n q。 接下来n-1行,分别表示点1到点n-1的父节点编号。 接下来q行,每行3个整数l r z。

输出格式:

输出q行,每行表示一个询问的答案。每个答案对201314取模输出

输入输出样例

输入样例#1: 复制

5 2
0
0
1
1
1 4 3
1 4 2
输出样例#1: 复制

8
5

说明

共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

题解

话说这题题解基本都是抄清华爷gconeice的吧……实在不会啊……

暴力的想法是,每次把要询问的点向上打上标记,然后让z点向上走,第一个遇到有标记的点就是lca

又因为lca的祖先也有标记,我们可以发现它的深度就是它祖先的标记总数

那么我们可以把每个点到根的路径都+1,然后询问z到根的和,就是答案了

很明显可以用树剖或LCT解决(然而本蒟蒻写不来LCT……)

多组询问如何解决?

我们可以把区间[l,r]的答案拆成[1,r]-[1,l-1]

然后把询问按端点排序,依次向后推,就可以满足条件了……

ps:hzwer大佬强无敌……代码看了我好久才弄明白怎么回事orz

 //minamoto
#include<bits/stdc++.h>
#define N 50005
#define mod 201314
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<15,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
typedef long long ll;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
int n,m,num,tot;
int sz[N],fa[N],son[N],cnt[N],rk[N],dep[N],top[N];
int ver[N],Next[N],head[N];
int sum[N<<],tag[N<<],l[N<<],r[N<<];
struct que{int z,ans1,ans2;}q[N];
struct data{int num,p;bool flag;}a[N<<];
bool operator <(data a,data b){return a.p<b.p;}
void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
void dfs1(int u){
sz[u]=;dep[u]=dep[fa[u]]+;
for(int i=head[u];i;i=Next[i]){
if(ver[i]==fa[u]) continue;
int v=ver[i];
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u){
if(top[u]==-) top[u]=u;
cnt[u]=++num,rk[num]=u;
if(son[u]) top[son[u]]=top[u],dfs2(son[u]);
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa[u]&&v!=son[u]) dfs2(v);
}
}
void pushdown(int p){
if(tag[p]){
int lc=p<<,rc=p<<|;
sum[lc]+=tag[p]*(r[lc]-l[lc]+);
sum[rc]+=tag[p]*(r[rc]-l[rc]+);
tag[lc]+=tag[p];
tag[rc]+=tag[p];
tag[p]=;
}
}
void build(int p,int ll,int rr){
l[p]=ll,r[p]=rr;
if(ll==rr) return;
int mid=(ll+rr)>>;
build(p<<,ll,mid);
build(p<<|,mid+,rr);
}
void update(int p,int ll,int rr)
{
if(ll<=l[p]&&rr>=r[p])
{
sum[p]+=r[p]-l[p]+;
++tag[p];
return;
}
pushdown(p);
int mid=(l[p]+r[p])>>;
if(ll<=mid) update(p<<,ll,rr);
if(rr>mid) update((p<<)+,ll,rr);
sum[p]=sum[p<<]+sum[p<<|];
}
void solve_update(int x,int f){
while(top[x]!=top[f]){
update(,cnt[top[x]],cnt[x]);
x=fa[top[x]];
}
update(,cnt[f],cnt[x]);
}
int query(int p,int ll,int rr)
{
if(ll<=l[p]&&rr>=r[p]) return sum[p];
pushdown(p);
int mid=(l[p]+r[p])>>;
int val=;
if(ll<=mid) val+=query(p<<,ll,rr);
if(rr>mid) val+=query((p<<)+,ll,rr);
return val;
}
int solve_query(int x,int f){
int sum=;
while(top[x]!=top[f]){
sum+=query(,cnt[top[x]],cnt[x]);
sum%=mod;
x=fa[top[x]];
}
sum+=query(,cnt[f],cnt[x]);sum%=mod;
return sum;
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),m=read();
memset(top,-,sizeof(top));
for(int i=;i<n;++i){
int x=read();add(x,i);
}
int tot=;
for(int i=;i<=m;++i){
int l=read(),r=read();
q[i].z=read();
a[++tot].p=l-,a[tot].num=i,a[tot].flag=;
a[++tot].p=r,a[tot].num=i,a[tot].flag=;
}
build(,,n);
sort(a+,a++tot);
dfs1(),dfs2();
int now=-;
for(int i=;i<=tot;++i){
while(now<a[i].p){
++now;
solve_update(now,);
}
int t=a[i].num;
if(!a[i].flag) q[t].ans1=solve_query(q[t].z,);
else q[t].ans2=solve_query(q[t].z,);
}
for(int i=;i<=m;++i)
printf("%d\n",(q[i].ans2-q[i].ans1+mod)%mod);
return ;
}

P4211[BZOJ 3626] [LNOI2014]LCA的更多相关文章

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

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

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

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

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

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

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

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

  5. [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】

    题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...

  6. BZOJ 3626 [LNOI2014]LCA:树剖 + 差分 + 离线【将深度转化成点权之和】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626 题意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0,n <= 50 ...

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

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

  8. bzoj 3626: [LNOI2014]LCA

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

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

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

随机推荐

  1. window.addEventListener()/window.postMessage(”text“, '*')

    1.设置监听 window.addEventListener('message', function (msg) { console.log(msg.data);}) 2.发送 message win ...

  2. list.contains

    list.contains(o),系统会对list中的每个元素e调用o.equals(e),方法,加入list中有n个元素,那么会调用n次o.equals(e),只要有一次o.equals(e)返回了 ...

  3. NBU 还原windows ORACLE数据库(BW)

    将0.92数据库还原到1.92,还原时间7月13日 1.查询所需要的控制日志 bplist -C bw-prd01 -s -- -e -- -k oracle_bw-prd01_0_92_arch - ...

  4. 【bzoj3437】小P的牧场

    3437: 小P的牧场 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 947  Solved: 542[Submit][Status][Discuss ...

  5. PHP 将HTML转成PDF文件,HTML 转word,Word 转Html

    html转 PDF 用MPDF ,Word转Html  纯PHP的方法暂未找到Word直接转PDF的方法 可以使用 LibreOffice 6.1  (Liunx,win) 皆可使用 Html转成PD ...

  6. Spring Boot gradle 集成servlet/jsp 教程及示例

    1.build.gradle 配置 注意,加入了war插件,在依赖中加入了jstl.tomcat-embed-jasper,这样才能运行jsp页面. buildscript { ext { sprin ...

  7. Golang作用域—坑

    先举个栗子,全局作用域变量,与 := 符号声明赋值新变量 package main import "fmt" var a = "GG" func main() ...

  8. SQLServer锁的机制

    SQLServer锁的机制:共享锁(S)排它锁(X)更新锁(U)意向共享 (IS)意向排它 (IX) 意向排它共享 (SIX)架构修改(Sch-M) 架构稳定性(Sch-S)大容量更新(BU)

  9. Efficient algorithms for polyploid haplotype phasing 多倍体单体型分型的有效算法

    背景:单倍型的推断,或沿着相同染色体的等位基因序列,是遗传学中的基本问题,并且是许多分析的关键组分,包括混合物图谱,通过下降和插补识别身份区域. 基于测序读数的单倍型定相引起了很多关注. 已经广泛研究 ...

  10. 删除重复记录的最新sql脚本

    delete from tb1   where id in(select t2.minnum from(select MIN(t1.id) as minnum,t1.col1 as ars ,COUN ...