题目链接: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;
}