Input
Output
Example
input | output |
---|---|
7 1 2 1 3 2 4 2 5 2 6 3 7 3 4 6 3 4 5 7 |
2 1 1 |
7 1 3 3 5 5 6 7 5 1 4 2 4 3 4 5 5 6 6 7 |
1 5 5 |
题意就不描述了,是个水题,预处理出i和i+1的lca,然后询问的时候跑线段树就行,这里线段树用到了寻找区间中最小的点的位置,存一下。
懒得改非递归,要手动开栈。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<algorithm> using namespace std; #define N 200010 int n,m; int v[N<<1],__next[N<<1],first[N],e; void AddEdge(int U,int V) { v[++e]=V; __next[e]=first[U]; first[U]=e; } int fa[N],dep[N],top[N],son[N],siz[N],tot; void dfs(int U) { siz[U]=1; for(int i=first[U];i;i=__next[i]) if(v[i]!=fa[U]) { fa[v[i]]=U; dep[v[i]]=dep[U]+1; dfs(v[i]); siz[U]+=siz[v[i]]; if(siz[v[i]]>siz[son[U]]) son[U]=v[i]; } } void df2(int U) { if(son[U]) { top[son[U]]=top[U]; df2(son[U]); } for(int i=first[U];i;i=__next[i]) if(v[i]!=fa[U]&&v[i]!=son[U]) { top[v[i]]=v[i]; df2(v[i]); } } int lca(int U,int V) { while(top[U]!=top[V]) { if(dep[top[U]]<dep[top[V]]) swap(U,V); U=fa[top[U]]; } if(dep[U]>dep[V]) swap(U,V); return U; } int minv[N<<2]; void update(int p,int v,int rt,int l,int r) { if(l==r) { minv[rt]=v; return; } int m=(l+r>>1); if(p<=m) update(p,v,rt<<1,l,m); else update(p,v,rt<<1|1,m+1,r); minv[rt]=min(minv[rt<<1],minv[rt<<1|1]); } int lcas[N]; int query(int ql,int qr,int rt,int l,int r) { if(ql<=l&&r<=qr) return minv[rt]; int m=(l+r>>1),res=2147483647; if(ql<=m) res=min(res,query(ql,qr,rt<<1,l,m)); if(m<qr) res=min(res,query(ql,qr,rt<<1|1,m+1,r)); return res; } int Find2(int v,int rt,int l,int r) { if(l==r) return l; int m=(l+r>>1); if(minv[rt<<1]==v) return Find2(v,rt<<1,l,m); else return Find2(v,rt<<1|1,m+1,r); } int Findp(int ql,int qr,int v,int rt,int l,int r) { if(ql<=l&&r<=qr) { if(minv[rt]==v) return Find2(v,rt,l,r); return -1; } int m=(l+r>>1); if(ql<=m) { int tmp=Findp(ql,qr,v,rt<<1,l,m); if(tmp!=-1) return tmp; } return Findp(ql,qr,v,rt<<1|1,m+1,r); } int main() { // freopen("j.in","r",stdin); int x,y; scanf("%d",&n); for(int i=1;i<n;++i) { scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } top[1]=1; dfs(1); df2(1); for(int i=1;i<n;++i) { lcas[i]=lca(i,i+1); update(i,dep[lcas[i]],1,1,n-1); } scanf("%d",&m); for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); if(x==y) printf("%d\n",x); else printf("%d\n",lcas[Findp(x,y-1,query(x,y-1,1,1,n-1),1,1,n-1)]); } return 0; }
【最近公共祖先】【线段树】URAL - 2109 - Tourism on Mars
原文:http://www.cnblogs.com/autsky-jadek/p/6337636.html