【luogu P3398 仓鼠找sugar】 题解

题目链接:https://www.luogu.org/problemnew/show/P3398
辣鸡树剖1300ms
倍增大法吼啊

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 550000;
const int maxlog = 20;
int n, m, root, f[maxn][maxlog], deep[maxn];
struct edge{
	int next, to;
}e[maxn<<2];
int head[maxn], cnt;
void add(int u, int v)
{
	e[++cnt].next = head[u]; e[cnt].to = v; head[u] = cnt;
	e[++cnt].next = head[v]; e[cnt].to = u; head[v] = cnt;
}
void dfs(int u, int p, int d)
{
	f[u][0] = p;
	deep[u] = d;
	for(int i = head[u]; i != -1; i = e[i].next)
	if(e[i].to != p) dfs(e[i].to, u, d+1);
}
void init()
{
	dfs(root, -1, 1);
	for(int i = 0; i + 1 < maxlog; i++)
	{
		for(int u = 1; u <= n; u++)
		if(f[u][i] < 0) f[u][i+1] = -1;
		else f[u][i+1] = f[f[u][i]][i];
	}
}
int LCA(int x, int y)
{
	if(deep[x] > deep[y]) swap(x,y);
	for(int i = 0; i < maxlog; i++)
	{
		if(deep[x] == deep[y]) break;
		if((deep[y]-deep[x])>>i&1) y = f[y][i];
	}
	if(x == y) return x;
	for(int i = maxlog-1; i >= 0; i--)
	{
		if(f[x][i] != f[y][i])
		{
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}
int main()
{
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&m);
	for(int i = 1; i < n; i++)
	{
		int u, v;
		scanf("%d%d",&u,&v);
		add(u,v);
	}
	root = 1;
	init();
    for(int i = 1; i <= m; i++)
    {
        int a, b, c, d, p, q;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        p = LCA(a,b);
        q = LCA(c,d);
        if((deep[p] > deep[c]) && (deep[p] > deep[d]))
        {
            printf("N
");
            continue;
        }
        if((deep[q] > deep[a]) && (deep[q] > deep[b]))		
        {
            printf("N
");
            continue;
        }
        if(deep[p] >= deep[q])
        {
        	if((LCA(p,c) == p) || (LCA(p,d) == p))
            {
                printf("Y
");
                continue;
            }
		}
		if(deep[q] >= deep[p])
        {
        	if((LCA(q,a) == q) || (LCA(q,b) == q))
            {
                printf("Y
");
                continue;
            }
		}
        printf("N
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/MisakaAzusa/p/9222797.html