HDU 5266
题意:以1为根,n个节点的树.Q次询问,每次询问[L,R],问编号L,L+1..R.这R-L+1个节点的LCA是多少?
n,Q<=3e5.
LCA(a,b)=x, LCA(c,d)=y. 则LCA(a,b,c,d)=LCA(x,y).
题意:以1为根,n个节点的树.Q次询问,每次询问[L,R],问编号L,L+1..R.这R-L+1个节点的LCA是多少?
n,Q<=3e5.
LCA(a,b)=x, LCA(c,d)=y. 则LCA(a,b,c,d)=LCA(x,y).
设F[k][i]为以i开头长度为2^k的区间的LCA. 用RMQ处理即可.
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=6e5+20,M=28;
int n,Q;
int d[N],p[N][30];
vector<int> e[N];
void dfs(int u,int fa)
{
if(fa)
d[u]=d[fa]+1;
p[u][0]=fa;
for(int i=1;i<M;i++)
p[u][i]=p[p[u][i-1]][i-1];
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
if(v==fa) continue;
dfs(v,u);
}
}
int LCA(int a,int b)
{
if(d[a]>d[b])
swap(a,b);
if(d[a]<d[b])
{
int del=d[b]-d[a];
for(int i=0;i<M;i++)
if((del>>i)&1)
b=p[b][i];
}
if(a!=b)
{
for(int i=M;i>=0;i--)
{
if(p[a][i]!=p[b][i])
a=p[a][i],b=p[b][i];
}
a=p[a][0],b=p[b][0];
}
return a;
}
int f[30][N];
void init()
{
for(int i=1;i<=n;i++)
f[0][i]=i;
for(int k=1;k<=M;k++)
{
for(int i=1;i+(1<<k)-1<=n;i++)
{
f[k][i]=LCA(f[k-1][i],f[k-1][i+(1<<(k-1))]);
}
}
}
int RMQ(int x,int y)
{
int k=0;
while(1<<(k+1)<=y-x+1)
k++;
return LCA(f[k][x],f[k][y-(1<<k)+1]);
}
int main()
{
while(cin>>n)
{
int u,v,x,y;
for(int i=1;i<=n;i++)
e[i].clear(),d[i]=0;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
scanf("%d",&Q);
init();
while(Q--)
{
scanf("%d%d",&x,&y);
int res=RMQ(x,y);
printf("%d\n",res);
}
}
return 0;
}