区队A 最近公共祖先

模板

#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
	euler[++size]= x;
	pos[x] = size;
	for(int i = 0 ;i < e[x].size() ; ++i)
	{
		int y = e[x][i];
		if(y != fa[x])
		{
			fa[y] = x;
			dep[y] = dep[x] + 1;
			dfs(y);
			euler[++size] = x;
		}
	}
}
int min_dep(int lhs,int rhs)
{
	return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
	log_2[1] = 0;
	for(int i = 2;i<=size;i++)
	{
		log_2[i] = log_2[i / 2] + 1;	
	}
	for(int i = 1;i<=size;i++)
	{
		st[0][i] = euler[i];
	}
	for(int i = 1;i<=log_2[size];i++)
	{
		for(int j = 1;j + (1 << i) - 1 <= size;++j)
		{
			st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i  - 1))]);
		}
	}
}
int query(int l,int r){
	int tmp = log_2[r-  l+ 1];
	return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
	int pos_x = pos[x],pos_y = pos[y];
	if(pos_x > pos_y)
	{
		swap(pos_x, pos_y);
	}
	return query(pos_x,pos_y);
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n,m,s;
	cin>>n>>m>>s;
	for(int i = 1;i<n;i++)
	{
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dep[s] = 0;
	size = 0;
	dfs(s);
	init();
	for(int i= 1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		cout<<lca(x,y)<<'\n';
	}
	return 0;
}

P8855 [POI 2002 R1] 商务旅行

首先可以设a = lca(x,y)

则x到y的距离为\(dep[x]+dep[y] - 2*dep[a]\)

Code:

#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
	euler[++size]= x;
	pos[x] = size;
	for(int i = 0 ;i < e[x].size() ; ++i)
	{
		int y = e[x][i];
		if(y != fa[x])
		{
			fa[y] = x;
			dep[y] = dep[x] + 1;
			dfs(y);
			euler[++size] = x;
		}
	}
}
int min_dep(int lhs,int rhs)
{
	return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
	log_2[1] = 0;
	for(int i = 2;i<=size;i++)
	{
		log_2[i] = log_2[i / 2] + 1;	
	}
	for(int i = 1;i<=size;i++)
	{
		st[0][i] = euler[i];
	}
	for(int i = 1;i<=log_2[size];i++)
	{
		for(int j = 1;j + (1 << i) - 1 <= size;++j)
		{
			st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i  - 1))]);
		}
	}
}
int query(int l,int r){
	int tmp = log_2[r-  l+ 1];
	return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
	int pos_x = pos[x],pos_y = pos[y];
	if(pos_x > pos_y)
	{
		swap(pos_x, pos_y);
	}
	return query(pos_x,pos_y);
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n;
	cin>>n;
	for(int i = 1;i<n;i++){
		int a,b;
		cin>>a>>b;
		e[a].push_back(b);
		e[b].push_back(a);
	}
	int m,cur;
	cin>>m>>cur;
	dep[1] = 0;
	size = 0;
	dfs(1);
	init();
	int ans = 0;
	for(int i = 2;i<=m;i++)
	{
		int nxt,a;
		cin>>nxt;
		a = lca(cur,nxt);
		ans += dep[cur] + dep[nxt] - 2 * dep[a];
		cur = nxt;
	}
	cout<<ans;
	
	return 0;
}

P2420 让我们异或吧

公式:\(dis[x] xor dis[y] ^ dis[a] ^ dis[a]\) 化简 -> \(dis[x] xor dis[y]\)

Code:

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
int size;
int sum[100010];
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<pii> e[500010];
void dfs(int x)
{
	euler[++size]= x;
	pos[x] = size;
	for(int i = 0 ;i < e[x].size() ; ++i)
	{
		int y = e[x][i].first,m = e[x][i].second;
		if(y != fa[x])
		{
			fa[y] = x;
			sum[y] = sum[x] ^ m;
			dfs(y);
			euler[++size] = x;
		}
	}
}
int min_dep(int lhs,int rhs)
{
	return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
	log_2[1] = 0;
	for(int i = 2;i<=size;i++)
	{
		log_2[i] = log_2[i / 2] + 1;	
	}
	for(int i = 1;i<=size;i++)
	{
		st[0][i] = euler[i];
	}
	for(int i = 1;i<=log_2[size];i++)
	{
		for(int j = 1;j + (1 << i) - 1 <= size;++j)
		{
			st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i  - 1))]);
		}
	}
}
int query(int l,int r){
	int tmp = log_2[r-  l+ 1];
	return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
	int pos_x = pos[x],pos_y = pos[y];
	if(pos_x > pos_y)
	{
		swap(pos_x, pos_y);
	}
	return query(pos_x,pos_y);
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n;
	cin>>n;
	for(int i = 1;i<n;i++){
		int a,b,w;
		cin>>a>>b>>w;
		e[a].push_back({b,w});
		e[b].push_back({a,w});
	}
	int m,cur;
	cin>>m;
	sum[1] = 0;
	size = 0;
	dfs(1);
	init();
	int ans = 0;
	for(int i = 1;i<=m;i++)
	{
		int u ,v;
		cin>>u>>v;
		cout<<(sum[u] ^ sum[v]) << '\n';
	}
	
	return 0;
}

P10113 [GESP202312 八级] 大量的工作沟通

结论:\(lca({x,y,z}) = lca(lca(x,y),z)\)

Code:

#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
int maxx[500010];
vector<int> e[500010];
void dfs(int x)
{
	euler[++size]= x;
	pos[x] = size;
	for(int i = 0 ;i < e[x].size() ; ++i)
	{
		int y = e[x][i];
		if(y != fa[x])
		{
			fa[y] = x;
			dep[y] = dep[x] + 1;
			maxx[y] = max(y,maxx[x]);
			dfs(y);
			euler[++size] = x;
		}
	}
}
int min_dep(int lhs,int rhs)
{
	return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
	log_2[1] = 0;
	for(int i = 2;i<=size;i++)
	{
		log_2[i] = log_2[i / 2] + 1;	
	}
	for(int i = 1;i<=size;i++)
	{
		st[0][i] = euler[i];
	}
	for(int i = 1;i<=log_2[size];i++)
	{
		for(int j = 1;j + (1 << i) - 1 <= size;++j)
		{
			st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i  - 1))]);
		}
	}
}
int query(int l,int r){
	int tmp = log_2[r-  l+ 1];
	return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
	int pos_x = pos[x],pos_y = pos[y];
	if(pos_x > pos_y)
	{
		swap(pos_x, pos_y);
	}
	return query(pos_x,pos_y);
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n,m,s;
	cin>>n;
	for(int i = 1;i<n;i++)
	{
		cin>>fa[i];
		e[fa[i]].push_back(i);
	}
	dep[0] = 0;
	size = 0;
	dfs(0);
	init();
	int q;
	cin>>q;
	for(int i= 1;i<=q;i++){
		int m,cur;
		cin>>m>>cur;
		for(int j = 2;j<=m;j++){
			int x;
			cin>>x;
			cur = lca(cur,x);
		}
		cout<<maxx[cur]<<'\n';
	}
	return 0;
}

P3128 [USACO15DEC] Max Flow P

树上差分

Code:

#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
int diff[500010];
int maxx;
void dfs(int x)
{
	euler[++size]= x;
	pos[x] = size;
	for(int i = 0 ;i < e[x].size() ; ++i)
	{
		int y = e[x][i];
		if(y != fa[x])
		{
			fa[y] = x;
			dep[y] = dep[x] + 1;
			dfs(y);
			euler[++size] = x;
		}
	}
}
int min_dep(int lhs,int rhs)
{
	return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
	log_2[1] = 0;
	for(int i = 2;i<=size;i++)
	{
		log_2[i] = log_2[i / 2] + 1;	
	}
	for(int i = 1;i<=size;i++)
	{
		st[0][i] = euler[i];
	}
	for(int i = 1;i<=log_2[size];i++)
	{
		for(int j = 1;j + (1 << i) - 1 <= size;++j)
		{
			st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i  - 1))]);
		}
	}
}
int query(int l,int r){
	int tmp = log_2[r-  l+ 1];
	return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
	int pos_x = pos[x],pos_y = pos[y];
	if(pos_x > pos_y)
	{
		swap(pos_x, pos_y);
	}
	return query(pos_x,pos_y);
}
int calc(int x){
	int sum = diff[x];
	for(int i = 0;i<e[x].size();i ++){
		int y = e[x][i];
		if(y != fa[x]){
			int tmp = calc(y);
//			maxx = max(maxx,tmp);
			sum += tmp;
		}
	}maxx = max(maxx,sum);
	return sum;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n,k;
	cin>>n>>k;
	for(int i = 1;i<n;i++)
	{
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dep[1] = 0;
	size = 0;
	dfs(1);
	init();
	for(int i= 1;i<=k;i++){
		int u,v;
		cin>>u>>v;
		int a=lca(u,v);
		++diff[u];
		++diff[v];
		--diff[a];
		if(dep[a] > 0) -- diff[fa[a]];
	}
	maxx = 0;
	calc(1);
	cout<<maxx;
	return 0;
}

P4281 [AHOI2008] 紧急集合 / 聚会

\(a = lca(x,y)\) ,\(b = lca(x,z)\),\(c = lca(y,z)\)

\(d[x] - d[a] + d[y] - d[b] + d[z] - d[b]\)

Code:

#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
	euler[++size]= x;
	pos[x] = size;
	for(int i = 0 ;i < e[x].size() ; ++i)
	{
		int y = e[x][i];
		if(y != fa[x])
		{
			fa[y] = x;
			dep[y] = dep[x] + 1;
			dfs(y);
			euler[++size] = x;
		}
	}
}
int min_dep(int lhs,int rhs)
{
	return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
	log_2[1] = 0;
	for(int i = 2;i<=size;i++)
	{
		log_2[i] = log_2[i / 2] + 1;	
	}
	for(int i = 1;i<=size;i++)
	{
		st[0][i] = euler[i];
	}
	for(int i = 1;i<=log_2[size];i++)
	{
		for(int j = 1;j + (1 << i) - 1 <= size;++j)
		{
			st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i  - 1))]);
		}
	}
}
int query(int l,int r){
	int tmp = log_2[r-  l+ 1];
	return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
	int pos_x = pos[x],pos_y = pos[y];
	if(pos_x > pos_y)
	{
		swap(pos_x, pos_y);
	}
	return query(pos_x,pos_y);
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i = 1;i<n;i++){
		int a,b;
		cin>>a>>b;
		e[a].push_back(b);
		e[b].push_back(a);
	}
	dep[1] = 0;
	size = 0;
	dfs(1);
	init();
	for(int i =1;i<=m;i++){
		int x,y,z;
		cin>>x>>y>>z;
		int xy = lca(x,y);
		int xz = lca(x,z);
		int yz = lca(y,z);
		int pos;
		if(xy == xz && xy == yz) pos = xy;
		else if(xy == yz) pos = xz;
		else if(xy == xz) pos = yz;
		else pos = xy;
		int ans = dep[x] + dep[y] + dep[z] - dep[xy] - dep[xz] - dep[yz];
		cout<<pos<<' '<<ans<<'\n';
	}
	return 0;
}

P3398 仓鼠找 sugar

\(x = lca(a,b)\) \(y = lca(c,d)\) \(dep[x] >= dep[y]\)

y是x祖先

Code:

#include<bits/stdc++.h>
using namespace std;
int size;
int fa[500010],dep[500010],pos[500010],log_2[1000010],euler[1000010],st[21][1000010];
vector<int> e[500010];
void dfs(int x)
{
	euler[++size]= x;
	pos[x] = size;
	for(int i = 0 ;i < e[x].size() ; ++i)
	{
		int y = e[x][i];
		if(y != fa[x])
		{
			fa[y] = x;
			dep[y] = dep[x] + 1;
			dfs(y);
			euler[++size] = x;
		}
	}
}
int min_dep(int lhs,int rhs)
{
	return dep[lhs] < dep[rhs] ? lhs : rhs;
}
void init()
{
	log_2[1] = 0;
	for(int i = 2;i<=size;i++)
	{
		log_2[i] = log_2[i / 2] + 1;	
	}
	for(int i = 1;i<=size;i++)
	{
		st[0][i] = euler[i];
	}
	for(int i = 1;i<=log_2[size];i++)
	{
		for(int j = 1;j + (1 << i) - 1 <= size;++j)
		{
			st[i][j] = min_dep(st[i - 1][j],st[i - 1][j + (1 << (i  - 1))]);
		}
	}
}
int query(int l,int r){
	int tmp = log_2[r-  l+ 1];
	return min_dep(st[tmp][l],st[tmp][r - (1 << tmp) + 1]);
}
int lca(int x,int y){
	int pos_x = pos[x],pos_y = pos[y];
	if(pos_x > pos_y)
	{
		swap(pos_x, pos_y);
	}
	return query(pos_x,pos_y);
}
int calc(int x,int y){
	int z=  lca(x,y);
	return dep[x] + dep[y] - 2 * dep[z];
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n,q;
	cin>>n>>q;
	for(int i = 1;i<n;i++){
		int u,v;
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dep[1] = 0;
	size = 0;
	dfs(1);
	init();
	for(int i = 1;i<=q;i++){
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		int x = lca(a,b),y = lca(c,d);
		if(dep[x] < dep[y]){
			swap(x,y);
			swap(a,c);
			swap(b,d);
		}
		cout<<(calc(c,x) + calc(x,d) == calc(c,d) ? "Y" : "N")<<'\n';
	}
	return 0;
}

P8972 『GROI-R1』 一切都已过去

转换成树上路径

2和5的因子数量

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 5e5 + 5;
const int inf = 1e16;

struct node {
    int y, w, dlp;
};

int n, m, s = 1, dep[N], dp[N][21], dis[N], cnt2[N], cnt5[N], a[N];
vector<node> nbr[N];

int count_two(int x) {
    if (x == 0) return inf;
    int cnt = 0;
    while (x % 2 == 0) {
        cnt++;
        x /= 2;
    }
    return cnt;
}

int count_five(int x) {
    if (x == 0) return inf;
    int cnt = 0;
    while (x % 5 == 0) {
        cnt++;
        x /= 5;
    }
    return cnt;
}

void pre_lca(int cur, int fa) {
    dp[cur][0] = fa;
    dep[cur] = dep[fa] + 1;
    for (int i = 1; (1 << i) <= dep[cur]; i++) {
        dp[cur][i] = dp[dp[cur][i-1]][i-1];
    }
    for (auto i : nbr[cur]) {
        int nxt = i.y;
        if (nxt != fa) {
            dis[nxt] = dis[cur] + i.dlp;
            cnt2[nxt] = cnt2[cur] + count_two(i.w);
            cnt5[nxt] = cnt5[cur] + count_five(i.w);
            pre_lca(nxt, cur);
        }
    }
}

int lca(int x, int y) {
    if (dep[x] > dep[y]) swap(x, y);
    for (int i = 20; i >= 0; i--) {
        if (dep[x] <= dep[dp[y][i]]) {
            y = dp[y][i];
        }
    }
    if (x == y) return x;
    for (int i = 20; i >= 0; i--) {
        if (dp[x][i] != dp[y][i]) {
            x = dp[x][i];
            y = dp[y][i];
        }
    }
    return dp[x][0];
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i < n; i++) {
        int x, y;
        double v;
        cin >> x >> y >> v;
        int dlp = 0;
        while (v != floor(v)) {
            v *= 10.0;
            dlp++;
        }
        nbr[x].push_back((node){y, (int)floor(v), dlp});
        nbr[y].push_back((node){x, (int)floor(v), dlp});
    }
    
    pre_lca(1, 0);
    
    for (; m; m--) {
        int x, y;
        cin >> x >> y;
        int tmp = lca(x, y);
        if (min(cnt2[x] + cnt2[y] - 2 * cnt2[tmp] + count_two(a[x]), 
                cnt5[x] + cnt5[y] - 2 * cnt5[tmp] + count_five(a[x])) >= 
            dis[x] + dis[y] - 2 * dis[tmp]) {
            cout << "Yes\n";
        } else {
            cout << "No\n";
        }
    }
    return 0;
}

P6374 「StOI-1」树上询问

倍增法

Code:

#include<bits/stdc++.h>
using namespace std;
int fa[20][500010],dep[500010];
vector<int> e[500010];
int sz[500010];
int n,m,s;
void dfs(int x)
{
    sz[x] = 1;
    for(int y : e[x])
    {
        if(y == fa[0][x]) continue;
        fa[0][y] = x;
        dep[y] = dep[x] + 1;
        for(int j = 0,a = x;fa[j][a] ; a = fa[j ++][a])
        {
            fa[j + 1][y]= fa[j][a];
        }dfs(y);
        sz[x] += sz[y];
    }
}

int lca(int x,int y){
    if(dep[x] < dep[y]) swap(x,y);
    int diff = dep[x] - dep[y];
    for(int i = 0;diff > 0 ;++i , diff >>= 1){
        if(diff & 1) x = fa[i][x];
    }
    if(x == y) return x;
    for(int i = 19;i >= 0 ; --i)
    {
        if(fa[i][x] != fa[i][y]){
            x = fa[i][x];
            y = fa[i][y];
        }
    }return fa[0][x];
}
bool check(int x,int y,int z)
{
    int k = lca(x,z);
    return ((lca(x,y) == y) || (lca(y,z) == y)) && lca(y,k) == k;
}
int Val(int x,int y)
{
    if(x == y) return 0;
    for(int i = 19;i >= 0;i--){
        if(dep[fa[i][x]] > dep[y]) x = fa[i][x];
    }
    return sz[x];
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    for(int i = 1;i < n;i ++){
        int x,y;
        cin>>x>>y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dep[1] = 0;
    fa[0][1] = 0;
    dfs(1);
    for(int i = 1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        int l = lca(x,y);
        if(l == z) cout<<n - Val(x,l) - Val(y,l)<<'\n';
        else if(check(x,z,l)) cout<<sz[z] - Val(x,z)<<'\n';
        else if(check(y,z,l)) cout<<sz[z] - Val(y,z)<<'\n';
        else cout<<"0\n";
    }
    return 0;
}

posted @ 2026-09-08 13:18  Zhenggeek  阅读(3)  评论(0)    收藏  举报