【LNOI 2014】 LCA
【题目链接】
【算法】
考虑求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的更多相关文章
- 【SDOI 2014】 旅行
		[题目链接] 点击打开链接 [算法] 树链剖分 每个宗教建一棵线段树,注意数据量大,要动态开点 [代码] #include<bits/stdc++.h> using namespace s ... 
- 【JLOI 2014】 松鼠的新家
		[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3631 [算法] 树上差分 [代码] #include<bits/stdc++. ... 
- 【AMPPZ 2014】 The Captain
		[题目链接] 点击打开链接 [算法] 按x轴排序,将相邻点连边 按y轴排序,将相邻点连边 然后对这个图跑最短路就可以了,笔者用的是dijkstra算法 [代码] #include<bits/st ... 
- 【JSOI 2014】序列维护
		[题目链接] 点击打开链接 [算法] 线段树 注意标记下传 [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 5 ... 
- 【TJOI 2014】 上升子序列
		[题目链接] 点击打开链接 [算法] 先考虑50分的做法 : f[i]表示以i结尾的本质不同的上升子序列的个数 则f[i] = sigma(f[j]) (j < i,a[j] < a[i] ... 
- 【PA 2014】Kuglarz
		[题目链接] 点击打开链接 [算法] sum[i]表示前i个杯子中,杯子底下藏有球的杯子总数 那么,知道[i,j]这段区间中,藏有球的 ... 
- 【NOI 2014】 动物园
		[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3670 [算法] KMP [代码] #include<bits/stdc++.h ... 
- 【HDU 2586】LCA模板
		在一棵树上 求2个点的最短距离.那么首先利用LCA找到2个点的近期公共祖先 公式:ans = dis(x) + dis(y) - 2 * dis(lca(x,y)) 这里的dis(x)指的上x距离根节 ... 
- 【Luogu P3379】LCA问题的倍增解法
		Luogu P3379 题意:对于两个节点,寻找他们的最近公共祖先. 一个显而易见的解法是对于每一个节点我们都往上遍历一遍,记录下它每一个祖先,然后再从另一个节点出发,一步一步往上走,找到以前记录过第 ... 
随机推荐
- 源码学习-Object类
			1.Object类是Java所有类的超类 2.查看Object的属性和方法,发现Object类没有属性,只有13个方法,其中7个本地方法. 3.接下来看具体的方法 3.1 Object() 默认的构造 ... 
- django-3 admin开启后台配置并展示表内容
			设置了superuser 之后,可以在run server 后, 通过浏览器访问后台,进行界面配置. 1. python manage.py creatersuperuser 此命令在manage.p ... 
- Not so Mobile  (针对递归输入的函数)
			Before being an ubiquous communications gadget, a mobile was just a structure made of strings and ... 
- 一个IT工薪族的4年奋斗成果
			关于标题:为了方便传播,使用了"最简化"的一段. 过段时间,考虑改为"大学毕业4年-回顾和总结(11):一个IT工薪族的4年奋斗成果(2012年6月17日~2016年6 ... 
- Unity Water Shader
			上图是一个物体浸入水中的效果 原理 我们使用相机渲染的整个场景的深度图减去需要忽略的模型的深度,这里忽略的是图中蓝色部分,就保留了其他的深度值. 用到Main Camera渲染的深度贴图: sampl ... 
- Nginx学习总结(4)——负载均衡session会话保持方法
			负载均衡时,为了保证同一用户session会被分配到同一台服务器上,可以使用以下方法: 1.使用cookie 将用户的session存入cookie里,当用户分配到不同的服务器时,先判断服务器是否存在 ... 
- js用for...in 这种遍历的方式
			var arr = new Array("first", "second", "third") for(var item in arr) { ... 
- amoeba连接mysql--ERROR 2006 (HY000): MySQL server has gone away
			amoeba下载地址:http://sourceforge.net/projects/amoeba/files amoeba version:amoeba-mysql-binary-2.1.0-RC5 ... 
- shit layui & select & re-render & bug
			shit layui https://www.layui.com/doc/modules/form.html#onselect https://www.layui.com/doc/element/fo ... 
- 走进矩阵树定理--「CodePlus 2017 12 月赛」白金元首与独舞
			n,m<=200,n*m的方阵,有ULRD表示在这个格子时下一步要走到哪里,有一些待决策的格子用.表示,可以填ULRD任意一个,问有多少种填法使得从每个格子出发都能走出这个方阵,答案取模.保证未 ... 
