【题目链接】

点击打开链接

【算法】

考虑求lca(x,y)的深度

我们可以将从根到x路径上的点都打上标记,然后,询问y到根上路径的权值和

那么,求sigma(depth(lca(i,z)))(l <= i <= r ),我们可以将区间[l,r]中的点依次打上标记,然后,询问点z到根路径

上的权值和

因为此题有多组询问,显然在线很难做,因此,我们考虑离线计算答案

求sigma(depth(lca(i,z))) (l <= i <= r),我们可以转化为

sigma(depth(lca(i,z))) ( 0 <= i <= r) - sigma(depth(lca(i,z))) (0 <= i <= l - 1)

那么,树链剖分/动态树都可以解决这道题,树链剖分的时间复杂度是O((n + q) log(n)^2)的,而动态树的时间复杂度是             O((n + q) log(n))的

【代码】

由于笔者太弱,不会动态树,所以这份代码是树链剖分的写法

#include<bits/stdc++.h>
using namespace std;
#define MAXM 50010
const int P = ; struct Edge
{
int to,nxt;
} e[MAXM];
struct Query
{
int pos,opt,z,id;
} q[MAXM*]; int i,n,m,f,timer,tot,cnt,now,l,r,z;
int dfn[MAXM],size[MAXM],top[MAXM],head[MAXM],son[MAXM],ans[MAXM],fa[MAXM]; struct SegmentTree
{
struct Node
{
int l,r;
int sum,tag;
} Tree[MAXM*];
inline void build(int index,int l,int r)
{
int mid;
Tree[index].l = l; Tree[index].r = r;
Tree[index].sum = Tree[index].tag = ;
if (l == r) return;
mid = (l + r) >> ;
build(index<<,l,mid);
build(index<<|,mid+,r);
}
inline void pushdown(int index)
{
int l = Tree[index].l,r = Tree[index].r;
int mid = (l + r) >> ;
if (Tree[index].tag)
{
Tree[index<<].sum = (Tree[index<<].sum + (mid - l + ) * Tree[index].tag) % P;
Tree[index<<|].sum = (Tree[index<<|].sum + (r - mid) * Tree[index].tag) % P;
Tree[index<<].tag = (Tree[index<<].tag + Tree[index].tag) % P;
Tree[index<<|].tag = (Tree[index<<|].tag + Tree[index].tag) % P;
Tree[index].tag = ;
}
}
inline void update(int index)
{
Tree[index].sum = (Tree[index<<].sum + Tree[index<<|].sum) % P;
}
inline void modify(int index,int l,int r,int val)
{
int mid;
if (Tree[index].l == l && Tree[index].r == r)
{
Tree[index].sum = (Tree[index].sum + (r - l + ) * val) % P;
Tree[index].tag = (Tree[index].tag + val) % P;
return;
}
pushdown(index);
mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= r) modify(index<<,l,r,val);
else if (mid + <= l) modify(index<<|,l,r,val);
else
{
modify(index<<,l,mid,val);
modify(index<<|,mid+,r,val);
}
update(index);
}
inline int query(int index,int l,int r)
{
int mid;
if (Tree[index].l == l && Tree[index].r == r) return Tree[index].sum;
pushdown(index);
mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= r) return query(index<<,l,r);
else if (mid + <= l) return query(index<<|,l,r);
else return (query(index<<,l,mid) + query(index<<|,mid+,r)) % P;
}
} T;
inline bool cmp(Query a,Query b)
{
return a.pos < b.pos;
}
inline void add(int u,int v)
{
tot++;
e[tot] = (Edge){v,head[u]};
head[u] = tot;
}
inline void dfs1(int u)
{
int i,v;
size[u] = ;
for (i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
dfs1(v);
size[u] += size[v];
if (size[v] > size[son[u]] || !son[u]) son[u] = v;
}
}
inline void dfs2(int u,int tp)
{
int i,v;
top[u] = tp;
dfn[u] = ++timer;
if (son[u]) dfs2(son[u],tp);
for (i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
if (son[u] != v) dfs2(v,v);
}
}
inline void modify(int pos)
{
int tp = top[pos];
while (tp)
{
T.modify(,dfn[tp],dfn[pos],);
pos = fa[tp]; tp = top[pos];
}
T.modify(,,dfn[pos],);
}
inline int query(int pos)
{
int tp = top[pos],ans = ;
while (tp)
{
ans = (ans + T.query(,dfn[tp],dfn[pos])) % P;
pos = fa[tp]; tp = top[pos];
}
ans = (ans + T.query(,,dfn[pos])) % P;
return ans;
} int main()
{ scanf("%d%d",&n,&m);
for (i = ; i < n; i++)
{
scanf("%d",&fa[i]);
add(fa[i],i);
}
dfs1();
dfs2(,);
T.build(,,timer);
for (i = ; i <= m; i++)
{
scanf("%d%d%d",&l,&r,&z);
if (l != ) q[++cnt] = (Query){l-,-,z,i};
q[++cnt] = (Query){r,,z,i};
}
sort(q+,q+cnt+,cmp);
now = -;
for (i = ; i <= cnt; i++)
{
while (now + <= q[i].pos)
{
now++;
modify(now);
}
if (q[i].opt == ) ans[q[i].id] = (ans[q[i].id] + query(q[i].z)) % P;
else ans[q[i].id] = (ans[q[i].id] - query(q[i].z) + P) % P;
}
for (i = ; i <= m; i++) printf("%d\n",ans[i]); return ;
}

【LNOI 2014】 LCA的更多相关文章

  1. 【SDOI 2014】 旅行

    [题目链接] 点击打开链接 [算法] 树链剖分 每个宗教建一棵线段树,注意数据量大,要动态开点 [代码] #include<bits/stdc++.h> using namespace s ...

  2. 【JLOI 2014】 松鼠的新家

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3631 [算法] 树上差分 [代码] #include<bits/stdc++. ...

  3. 【AMPPZ 2014】 The Captain

    [题目链接] 点击打开链接 [算法] 按x轴排序,将相邻点连边 按y轴排序,将相邻点连边 然后对这个图跑最短路就可以了,笔者用的是dijkstra算法 [代码] #include<bits/st ...

  4. 【JSOI 2014】序列维护

    [题目链接] 点击打开链接 [算法] 线段树 注意标记下传 [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 5 ...

  5. 【TJOI 2014】 上升子序列

    [题目链接] 点击打开链接 [算法] 先考虑50分的做法 : f[i]表示以i结尾的本质不同的上升子序列的个数 则f[i] = sigma(f[j]) (j < i,a[j] < a[i] ...

  6. 【PA 2014】Kuglarz

    [题目链接]            点击打开链接 [算法]            sum[i]表示前i个杯子中,杯子底下藏有球的杯子总数            那么,知道[i,j]这段区间中,藏有球的 ...

  7. 【NOI 2014】 动物园

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3670 [算法] KMP [代码] #include<bits/stdc++.h ...

  8. 【HDU 2586】LCA模板

    在一棵树上 求2个点的最短距离.那么首先利用LCA找到2个点的近期公共祖先 公式:ans = dis(x) + dis(y) - 2 * dis(lca(x,y)) 这里的dis(x)指的上x距离根节 ...

  9. 【Luogu P3379】LCA问题的倍增解法

    Luogu P3379 题意:对于两个节点,寻找他们的最近公共祖先. 一个显而易见的解法是对于每一个节点我们都往上遍历一遍,记录下它每一个祖先,然后再从另一个节点出发,一步一步往上走,找到以前记录过第 ...

随机推荐

  1. Vue实例方法之事件的实现

    开始 这段时间一直在看vue的源码,源码非常多和杂,所以自己结合资料和理解理出了一个主线,然后根据主线去剥离其他的一些知识点,然后将各个知识点逐一学习.这里主要是分析的Vue事件处理的实现. 正文 一 ...

  2. ubuntu 安装python 编程环境

    1. 安装python sudo add-apt-repository ppa:fkrull/deadsnakessudo apt-get updatesudo apt-get install pyt ...

  3. sql server 备份计划

    SSMS 1.管理 2.维护计划 3.维护计划向导 或者 1. server 代理 2. 作业 3. 新建作业 备份计划时间尽量选在闲时, 例如午夜

  4. Not so Mobile (针对递归输入的函数)

      Before being an ubiquous communications gadget, a mobile was just a structure made of strings and ...

  5. Uva 839天平(二叉树dfs, 递归建树)

    题意: 给定一个天平长度 输入格式为 wl dl wr dr 分别代表天平左边长度,左边重量, 右边长度, 右边重量. 如果重量为0, 说明下面还有一个天平, 递归给出. 样例输入:10 2 0 40 ...

  6. hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷·三

    原题地址 看上去非常复杂, 实际上是这一系列最简单的一步,本质上是个搜索过程,相比于前一道题,可以不用策略三,而且题目的数据规模超级小,所以暴力搜索就能过. 把尚未确定的点放在一个unsettled列 ...

  7. noip模拟赛 少女

    分析:每个连通块都是独立的,对一个连通块进行分析.如果边数>点数,显然是不可能的,因为每条边要分配给一个点,至少有一个点分配了两次以上.如果边数=点数,就形成了环,有两种方案,顺时针一个环,逆时 ...

  8. vue2.0一个书城实例

    gitHub克隆地址 git clone https://github.com/Webxiaoyaun/vue-book.git 点击去Github下载 ## 一个书城 ## 有增加,修改,缓存,懒加 ...

  9. ajax接收json数据到js解析

    今天又学到了一点新知识,脑子记不住东西特把它记录下来! 页面ajax请求后台时一般都是返回字符串进行判断,要是返回list或者对象时该怎么办? 第一种:ajax接收到list并返回给前台 js代码: ...

  10. QT-Embedded-4.5.3在海思35xx上移植

    QT4.5.3在海思3520A上移植步骤-修订版 2015年3月29日星期日, 16:59:03 1.首先要保证已经安装了海思的交叉编译器: #arm-hi  + Tab key to show wh ...