弱啊弱啊,我用了扩展指令,然后大牛告诉我,只对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; }
原文:http://www.cnblogs.com/jie-dcai/p/4559297.html