题意:给一颗树,Q次询问L,L+1,L+2...R的LCA
以LCA为权建线段树,直接查询即可
(我用树剖找LCA)
代码:
#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#define ull unsigned long long
#define ll long long
#define inf 300009
#define infm 3000009
#define INF (int) 1e9
#define rd(n) {n=0;char ch;int f=0;do{ch=getchar();if(ch=='-'){f=1;}}while(ch<'0'||ch>'9');while('0'<=ch&&ch<='9'){n=(n<<1)+(n<<3)+ch-48;ch=getchar();}if(f)n=-n;}
using namespace std;
int dep[inf],siz[inf],son[inf],top[inf],fa[inf];
int n,q;
struct edge{
int y,nxt;
}e[inf*2];
int head[inf],ecnt;
void addedge(int x,int y){
ecnt++;
e[ecnt].nxt=head[x];
e[ecnt].y=y;
head[x]=ecnt;
return;
}
void dfs1(int u,int last){
fa[u]=last;
siz[u]=1;
son[u]=-1;
for (int i=head[u];i;i=e[i].nxt){
int v=e[i].y;
if (v!=last){
dep[v]=dep[u]+1;
dfs1(v,u);
siz[u]+=siz[v];
if (son[u]<0 || siz[v]>siz[son[u]]){
son[u]=v;
}
}
}
return;
}
void dfs2(int u,int tp){
top[u]=tp;
if (son[u]>0){
dfs2(son[u],tp);
}
for (int i=head[u];i;i=e[i].nxt){
int v=e[i].y;
if (v!=fa[u] && v!=son[u]){
dfs2(v,v);
}
}
return;
}
int getlca(int u,int v){
while (top[u]!=top[v]){
if (dep[top[u]]<dep[top[v]]){
swap(u,v);
}
u=fa[top[u]];
}
if (u==v){
return u;
}
return dep[u]>dep[v]?v:u;
}
int lca[inf*4];
void ST_pushup(int u){
lca[u]=getlca(lca[u*2],lca[u*2+1]);//利用LCA的性质建线段树
return;
}
void ST_build(int u,int l,int r){
if (l==r){
lca[u]=l;
return;
}
int mid=(l+r)/2;
ST_build(u*2,l,mid);
ST_build(u*2+1,mid+1,r);
ST_pushup(u);
return;
}
int ST_query(int u,int l,int r,int L,int R){
if (L<=l && r<=R){
return lca[u];
}
int mid=(l+r)/2,l1=-1,l2=-1;
if (L<=mid){
l1=ST_query(u*2,l,mid,L,R);
}
if (R>mid){
l2=ST_query(u*2+1,mid+1,r,L,R);
}
if (l1<0){
return l2;
}
else if (l2<0){
return l1;
}
else{
return getlca(l1,l2);
}
}
int main(){
int x,y;
while (~scanf("%d",&n)){
for (int i=0;i<=n;i++){
head[i]=0;
}
ecnt=0;
for (int i=1;i<n;i++){
rd(x) rd(y)
addedge(x,y);
addedge(y,x);
}
dep[1]=0;
dfs1(1,0);
dfs2(1,1);//树剖
ST_build(1,1,n);//建树
rd(q);
for (int i=0;i<q;i++){
rd(x) rd(y)
printf("%d\n",ST_query(1,1,n,x,y));
}
}
return 0;
}