intさわだんのBlack History

刹那的レジェンドになりたい。

LCA memo 最小共通祖先 lca c++

http://abc014.contest.atcoder.jp/tasks/abc014_4

完全にmemoで保存用

O(N^2)

#include <bits/stdc++.h>

using namespace std;

const int M = 100010;

vector<int> G[M];
int root;
int n,q;
int parent[M];
int depth[M];

void dfs(int v,int p,int d){
	parent[v] = p;
	depth[v] = d;
	for(int i = 0;i < G[v].size();i++){
		if(G[v][i] != p) dfs(G[v][i],v,d + 1);
	}
}

void init(){
	dfs(root,-1,0);
}

int lca(int u,int v){
	while(depth[u] > depth[v])u = parent[u];
	while(depth[v] > depth[u])v = parent[v];
	while(u != v){
		v = parent[v];
		u = parent[u];
	}
	return u;
}

int main(){
	scanf("%d",&n);
	root = 1;
	for(int i = 0;i < n-1;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	init();
	scanf("%d",&q);

	for(int i = 0;i < q;i++){
		int a,b;
		scanf("%d%d",&a,&b);

		int par = lca(a,b);
		printf("%d\n",(depth[a]-depth[par])+(depth[b]-depth[par])+1);
	}
	return 0;
}

O(N log N)

#include <bits/stdc++.h>

using namespace std;

const int M = 100010;
const int MLV = 18; 
vector<int> G[M];
int root;
int n,q;
int parent[MLV][M];
int depth[M];

void dfs(int v,int p,int d){
	parent[0][v] = p;
	depth[v] = d;
	for(int i = 0;i < G[v].size();i++){
		if(G[v][i] != p) dfs(G[v][i],v,d + 1);
	}
}

void init(int V){
	dfs(root,-1,0);
	for(int k = 0;k+1 < MLV;k++){
		for(int v = 1;v <= V;v++){
			if(parent[k][v] < 0) parent[k+1][v] = -1;
			else parent[k+1][v] = parent[k][parent[k][v]];
		}
	}
}

int lca(int u,int v){
	if(depth[u] > depth[v]) swap(u,v);
	for(int k = 0;k < MLV;k++){
		if((depth[v] - depth[u]) >> k & 1){
			v = parent[k][v];
		}
	}
	if(u == v)return u;
	for(int k = MLV-1;k >= 0;k--){
		if(parent[k][u] != parent[k][v]){
			u = parent[k][u];
			v = parent[k][v];
		}
	}
	return parent[0][u];
}

int main(){
	scanf("%d",&n);
	root = 1;
	for(int i = 0;i < n-1;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	init(n);
	scanf("%d",&q);

	for(int i = 0;i < q;i++){
		int a,b;
		scanf("%d%d",&a,&b);

		int par = lca(a,b);
		printf("%d\n",(depth[a]-depth[par])+(depth[b]-depth[par])+1);
	}
	return 0;
}

RMQでの実装(バグる
つらい

#include <bits/stdc++.h>

using namespace std;

const int M = 100010;

vector<int> G[M];
int vs[M*2-1];
int depth[M * 2 - 1];
int id[M];
int root;
int K;
int haji;
int seg[4 * M];
void rmq_init(int n_){
	haji = 1;
	while(haji < n_)haji *= 2;
	for(int i = 0;i < haji*2-1;i++){
		seg[i] = -1;
	}
}

void update(int k,int a){
	k += haji - 1;
	seg[k] = a;
	while(k > 0){
	//	seg[k] = min(depth[seg[k*2+1]],depth[seg[k*2+2]]);
		int a = seg[k*2+1],b = seg[k*2+2];
		if(a != -1 && b != -1){
			seg[k] = depth[a] < depth[b] ? a : b;
		}else if(a == -1){
			seg[k] = b;
		}else{
			seg[k] = a;
		}
	}
}

int query(int a,int b,int k,int l,int r){
	if(r <= a || b <= l)return -1;
	if(a <= l && r <= b) return seg[k];
	else{
		int vl = query(a,b,k*2+1,l,(l+r)/2);
		int vr = query(a,b,k*2+2,(l+r)/2,r);
		if(vl == -1){
			return vr;
		}else if(vr == -1){
			return vl;
		}else{
			return (depth[vl] < depth[vr] ? vl : vr);
		}
	}
}
void dfs(int v,int p,int d,int &k){
	id[v] = k;
	vs[k] = v;
	depth[k++] = d;
	for(int i = 0;i < G[v].size();i++){
		if(G[v][i] != p){
			dfs(G[v][i],v,d+1,k);
			vs[k] = v;
			depth[k++] = d;
		}
	}
}

void init(int V){
	int k = 0;
	dfs(root,-1,0,k);
	K = V;
	rmq_init(V*2-1);
}

int lca(int u,int v){
	return vs[query(min(id[u],id[v]),max(id[u],id[v])+1,0,0,haji)];
}

int main(){
	int n,q;
	int root = 1;
	scanf("%d",&n);
	for(int i = 0;i < n-1;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	init(n);
	for(int i = 0;i <= K;i++){
		update(i,i);
	}
	for(int i = 0;i < K;i++){
		printf("%d\n",seg[i]);
	}
	scanf("%d",&q);
	for(int i = 0;i < q;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		int par = lca(a,b);
		printf("%d\n",(depth[id[a]] - depth[id[par]]) + (depth[id[b]] - depth[id[par]]) + 1);
	}
	return 0;
}