首页 > 其他分享 >欧拉序+ST表 O(nlogn+q)求LCA

欧拉序+ST表 O(nlogn+q)求LCA

时间:2023-03-20 20:58:50浏览次数:32  
标签:idx int len ST LCA nlogn 欧拉

欧拉序:每次遍历到树上的一个点,就加进欧拉序

1

2 3

​ 4 5

这颗树的欧拉序是121343431

这样我们可以发现一个重要的性质:两个点的LCA是欧拉序之间dep最小的点

易发现这是对的,因为LCA肯定会在欧拉序之间,而LCA的祖先不会,因为如果会,说明LCA的这颗子树已经被遍历完了,那之后不会再有另一个节点

因此我们dfs建立欧拉序,在欧拉序上建ST表,每次查u,v的LCA,等价于查找$$[pos[u],pos[v]]$$在ST表上的最小值

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 5e5+10,M=2*N;
int n, m, k, T;
int h[N],e[M],ne[M],idx;
PII val[22][2*N];
int dep[N],_,pos[N];
int Log2[2*N];
void add(int a, int b) {
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
unsigned int A, B, C;
inline unsigned int rng61() {
	A ^= A << 16;
	A ^= A >> 5;
	A ^= A << 1;
	unsigned int t = A;
	A = B;
	B = C;
	C ^= t ^ A;
	return C;
}
void dfs(int u, int p) {
	//cout<<u<<'!'<<endl;
	dep[u]=dep[p]+1;
	val[0][++_] = {dep[u],u};
	pos[u]=_;
	for (int i = h[u]; ~i; i = ne[i]) {
		int k=e[i];
		if(k==p)continue;
		dfs(k,u);
		val[0][++_]={dep[u],u};
	}
}
void initST() {
	for(int i=2;i<=_;i++)Log2[i]=Log2[i/2]+1;
	for(int i=1;i<=20;i++)
		for (int j = 1; j+(1<<i)-1 <= _; j++) {
			val[i][j]=min(val[i-1][j],val[i-1][j+(1<<i-1)]);
		}
}
int query(int l, int r) {
	if(l>r)swap(l,r);
	int len=Log2[r-l+1];
	return min(val[len][l],val[len][r-(1<<len)+1]).second;
}
int main(){
	memset(h,-1,sizeof h);
	scanf("%d%d%u%u%u", &n, &m, &A, &B, &C);
	// 输入树边
	for (int i = 1; i < n; i++) {
		int a,b;
		scanf("%d%d",&a,&b);
		add(a,b),add(b,a);
	}
	dfs(1,0);
	initST();
	LL res=0;
	for (int i = 1; i <= m; i++) {
		unsigned int u = rng61() % n + 1, v = rng61() % n + 1;
		//printf("%d %d %d\n",u,v,query(pos[u],pos[v]));
		res^=1LL*i*query(pos[u],pos[v]);
	}
	printf("%lld",res);
}

Tip:

建ST表有个小技巧,可以建一个pair的ST,first存值,second存对应的dep最小的点,这样每次取min的时候可以自动保存最小值所在的点,而不需要另开一个数组

标签:idx,int,len,ST,LCA,nlogn,欧拉
From: https://www.cnblogs.com/codjjj/p/17237723.html

相关文章

  • 如何自动化测试你的接口?—— Rest Assured
    前言不知道大家的项目是否都有对接口API进行自动化测试,反正像我们这种小公司是没有的。由于最近一直被吐槽项目质量糟糕,只能研发自己看看有什么接口测试方案。那么在本文......
  • instanceof和类型转换
    类型转换父类引用转向子类对象把子类转换为父类,向上转型把父类转换为子类,向下转型,强制转换方便方法的调用publicstaticvoidmain(String[]args){......
  • requests下载大文件,断点下载
    前言requests.get()请求一个视频连接链接,如果视频太大怎么办?requests.get()下载到一半暂停了,想要接着下载怎么办?REQUESTS如何友好地请求下载大文件?当我们用requests.ge......
  • Test
    第一次用博客园,测试一下。testtesttesttesttesttesttesttesttesttesttest\(\mathcal{test}\)\(\mathcal{O}(n\logn)\)\(\texttt{test}\)\[\Hu......
  • 【多态】中的【instanceof】
    /***Bysleeon2023/3/20*父类引用指向子类对象,这个引用既属于子类,又属于父类*但是如果各自创建对象的话,父类对象就不属于子类*/publicclassTest{pub......
  • Android Studio通过jdbc连接MySQL
    1、下载MySQL-connector-jave.jar包地址如下:https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.46 2、将jar包移到如图所示的位置,然后右键addasl......
  • java.lang.AssertionError: The following types on /data/ must be associated with
    1.自己在data/tcpdump 下定义了 tcpdump_file类型的文件 file_context/data/tcpdump(/.*)?u:object_r:tcpdump_file:s0file.tetypetcpdump_file,file_type;2......
  • debian ipxe-qemu (version 1.0.0+git-20190125.36a4c85-5 bug and install kvm+qemu+
    环境debiansid/testingbug1我发现了在sid中的一个BUG,并在debianwiki中找到了这个BUG的记录BUG2以上我们得知了,这个重要BUG不影响我们本身,所以直接安装安装可以只安装QEMU......
  • amd64/UEFI/systemd/gnome/gentoo安装过程记录
    注意本人使用install-amd64-minimal-20220123T170538Z.isostage3-amd64-desktop-systemd-20220116T170534Z.tar.xz配置信息CPU:Inteli5-8300H(8)@4.000GHzGPU:NVIDIA......
  • 去重 : 去除ArrayList<Object>里面的重复记录
    [color=red][b]针对基础类型:[/b][/color]ArrayList<String>result=newArrayList<String>();for(Strings:sources){if(Collections.freque......