弱啊弱啊,我用了扩展指令,然后大牛告诉我,只对VC++有用,对G++没用的。。shit,三题就这样没了。
方法是使用ST在线算法,O(1)查询,然后用线段树维护。。呃感觉这个好慢。看了大斌神的是用LCA倍增+维护一个表 ,得学习一下。。。
先贴弱的代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=300015;
struct Edge{
int u,v,next;
}edge[N*2];
int head[N],tot,dtot;
int dp[N*2][20];
int ver[2*N],R[2*N],first[N],dir[N];
bool vis[N];
int ans;
int tag[N*4];
void addedge(int u,int v){
edge[tot].u=u;
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void dfs(int u ,int dep) {
vis[u] = true; ver[++dtot] = u; first[u] = dtot; R[dtot] = dep;
for(int k=head[u]; k!=-1; k=edge[k].next)
if( !vis[edge[k].v] ) {
int v = edge[k].v ;
dfs(v,dep+1);
ver[++dtot] = u; R[dtot] = dep;
}
}
void ST(int n) {
for(int i=1;i<=n;i++)
dp[i][0] = i;
for(int j=1;(1<<j)<=n;j++) {
for(int i=1;i+(1<<j)-1<=n;i++) {
int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1];
dp[i][j] = R[a]<R[b]?a:b;
}
}
}
int RMQ(int l,int r) {
int k=0;
while((1<<(k+1))<=r-l+1)
k++;
int a = dp[l][k], b = dp[r-(1<<k)+1][k];
return R[a]<R[b]?a:b;
}
int LCA(int u ,int v) {
int x = first[u] , y = first[v];
if(x > y) swap(x,y);
int res = RMQ(x,y);
return ver[res];
}
void query(int rt,int l,int r,int L,int R){
// cout<<L<<" "<<R<<endl;
if(tag[rt]!=-1&&l<=L&&R<=r){
if(ans==-1) ans=tag[rt];
else {
ans=LCA(ans,tag[rt]);
}
return ;
}
else if(L==R){
// cout<<L<<" "<<ans<<endl;
tag[rt]=L;
if(ans==-1)
ans=L;
else{
ans=LCA(ans,L);
}
return ;
}
int m=(L+R)>>1;
if(r<=m){
query(rt<<1,l,r,L,m);
}
else if(l>=m+1){
query(rt<<1|1,l,r,m+1,R);
}
else{
query(rt<<1,l,r,L,m);
query(rt<<1|1,l,r,m+1,R);
}
if(tag[rt<<1]!=-1&&tag[rt<<1|1]!=-1)
tag[rt]=LCA(tag[rt<<1],tag[rt<<1|1]);
}
int main(){
int n,q,u,v;
while(scanf("%d",&n)!=EOF){
memset(head,-1,sizeof(int)*(n+5));
memset(vis,false,sizeof(bool)*(n+5));
memset(tag,-1,sizeof(int)*(n*4));
tot=0;
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dtot=0;
dfs(1,1);
ST(2*n-1);
tag[1]=1;
scanf("%d",&q);
// printf("%d",LCA(2,3));
// printf("%d",LCA(1,2));
// printf("%d",LCA(3,4));
while(q--){
scanf("%d%d",&u,&v);
ans=-1;
query(1,u,v,1,n);
printf("%d\n",ans);
}
}
return 0;
}