SP10707 COT2 - Count on a tree II (树上莫队)

传送门
普通莫队是对一段一维的序列上操作的算法,即使带修莫队也是增加一个时间轴修改的序列也是一维的,如果对于一个树能否操作呢?可以将对树处理成一个欧拉序来实现,欧拉序是在dfs序的基础上在绕回每个点时将这个点填进去的序列。举个例子:
在这里插入图片描述
dfs序:12345678
欧拉序:1233445526778861
定义:s[i]表示节点i入栈的时间戳,t[i]表示节点i出栈的时间戳。
所以欧拉序的长度是2n的,对树上两点u和v之间的路径有两种情况(假设u的深度比v小):
u是v的祖先:那么s[u]到s[v]之间的点(出现两次的点除外)都在u到v之间的路径上,u=1,v=5时就对应欧拉序上区间[1,7]。
u不是v的祖先,这种情况下s[u]到s[v]之间欧拉序u会出现两次,所以要用t[u]到s[v],但是这样的话u和v的lca没有出现在欧拉序内,所以移动区间时还要将lca加进去,记得统计过后在把lca的贡献去掉。
这样就能将树上的路径查询转变为欧拉序的区间查询,套莫队就完了。
欧拉序dfs就可以,求lca可以树剖,欧拉序顺带就出来了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=100010;
int n,m,a[N],nums[N];
int h[N],ne[N],e[N],idx;
void add(int a,int b)
{
   
	e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
int dep[N],sz[N],son[N],fa[N],dfn[N],top[N],cnt;
int oula[N],s[N],t[N];
void dfs1(int u,int p)
{
   
	sz[u]=1;
	oula[++cnt]=u;
	s[u]=cnt;
	for(int i=h[u];~i;i=ne[i])
	{
   
		int v=e[i];
		if(v==p) continue;
		dep
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值