【题目链接】

点击打开链接

【算法】

考虑求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 ;
}

最新文章

  1. 【Telerik】&lt;telerik:RadGridView/&gt;控件的使用
  2. 黑马程序员+ADO.Net基础(下)
  3. iOS开发小技巧--TextField的细节处理,键盘中return键的处理
  4. Locking
  5. JS入门-慕课网
  6. 【英文】Bingo口语笔记(18) - Cover系列
  7. Unity 3D 文件导入出错误解决方法以及unity圣典离线版下载地址
  8. JENKINS里,如何为SLAVE配置多个不同的JAVA环境?
  9. jquery实现复选框全选反选
  10. css之自动换行-设计师零张
  11. leetcode Search in Rotated Sorted Array python
  12. Entity Framework查询注意
  13. 原来你是这样的JAVA[02]-包、传参、构造器
  14. Struts2.3.34+Hibernate 4.x+Spring4.x 整合二部曲之下部曲
  15. python:浅析python 中__name__ = &#39;__main__&#39; 的作用(转载)
  16. linux下 如何切换到root用户
  17. springboot添加自定义注解
  18. Docker 日志都在哪里?怎么收集?
  19. 6.3 OrderBy 优化
  20. Python-递归初识-50

热门文章

  1. js中给正则传参、传递变量
  2. Anaconda基本用法
  3. 得到JavaWeb项目在Tomcat中的运行路径
  4. CF-697B Barnicle与691C Exponential notation
  5. Windows Server 2012 防火墙如何添加端口例外的方法(转)
  6. 使用mysql-proxy 快速实现mysql 集群 读写分离
  7. hihoCoder#1109 最小生成树三&#183;堆优化的Prim算法
  8. codevs——1385 挤牛奶
  9. Eclipse-Java代码规范和质量检查插件-阿里编码规约
  10. how to read openstack code