H - Tourism on Mars URAL - 2109 -LCA-線段樹
阿新 • • 發佈:2018-12-01
-
H - Tourism on Mars
URAL - 2109 - 題意:給你 n 個點,接下來 n-1 行,每行輸入 u, v 代表 u 點和 v 點無向邊。 有 q 次詢問。
- u 到 v 的道路中,距離 1 點最近的點,是main attraction 點。
- 每次詢問輸入 u, v 問,u 到 u+1 main attraction 點,u+1 到 u+2重要的點…. v-1 到 v 重要的點中哪個點距離 1最更近.
- 思路:n個點,n-1條邊,是一棵樹,所以任意兩點最短路徑唯一,而且這條最短路徑就是這兩個點分別到它們的公共祖先,
- 那麼任意兩點之間的路徑上距離1最近的點,一定是他們的最近公共祖先,所以利用倍增求LCA預處理出他們的公共祖先
- 然後線段樹維護一下一段區間內距離1最近的main attraction 點,由於判斷與1的遠近需要deep深度來判斷,所以維護了一下
- 深度的最小值,還需要知道是哪個點同時維護了一下距離1最近的點,然後每個節點存的是i與i+1的公共祖先,所以線段樹
- 只需要建一個1-n-1的即可,這樣的話輸入n==1是需要特判否則直接建樹會RE,感謝鄭延亮,tql-http://zyl1213.top/blog/
-
#include<bits/stdc++.h> using namespace std; #define maxn 1234567 int n,q,u,v,cnt,head[maxn],ans; int deep[maxn],dp[maxn][30],id; struct tre { int l,r,depth,fa; } tree[maxn*4]; struct node { int v,to; } edge[maxn]; void add(int u,int v) { edge[++cnt].v=v; edge[cnt].to=head[u]; head[u]=cnt; } void dfs(int cur,int pre) { deep[cur]=deep[pre]+1; dp[cur][0]=pre; for(int i=1; (1<<i)<=deep[cur]; i++) dp[cur][i]=dp[dp[cur][i-1]][i-1]; for(int i=head[cur]; i!=-1; i=edge[i].to) if(edge[i].v!=pre) dfs(edge[i].v,cur); } int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); for(int i=22; i>=0; i--) if(deep[x]-(1<<i)>=deep[y]) x=dp[x][i]; if(x==y)return x; for(int i=22; i>=0; i--) if(dp[x][i]!=dp[y][i]) { x=dp[x][i]; y=dp[y][i]; } return dp[x][0]; } void up(int root) { if(tree[root*2].depth<tree[root*2+1].depth) { tree[root].depth=tree[root*2].depth; tree[root].fa=tree[root*2].fa; } else { tree[root].depth=tree[root*2+1].depth; tree[root].fa=tree[root*2+1].fa; } } void build(int root,int l,int r) { tree[root].l=l; tree[root].r=r; if(l==r) { tree[root].fa=lca(l,l+1); tree[root].depth=deep[tree[root].fa]; return ; } int mid=(l+r)/2; build(root*2,l,mid); build(root*2+1,mid+1,r); up(root); } void query(int root,int l,int r) { if(tree[root].l==l&&tree[root].r==r) { if(tree[root].depth<ans) { ans=tree[root].depth; id=tree[root].fa; } return ; } int mid=(tree[root].l+tree[root].r)/2; if(l>mid)query(root*2+1,l,r); else if(r<=mid)query(root*2,l,r); else { query(root*2,l,mid); query(root*2+1,mid+1,r); } } int main() { deep[0]=0; memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=1; i<n; i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } scanf("%d",&q); if(n==1) { while(q--) { scanf("%d%d",&u,&v); printf("1\n"); } return 0; } dfs(1,0); build(1,1,n-1); while(q--) { ans=1e8; scanf("%d%d",&u,&v); if(u==v)printf("%d\n",u); else { query(1,u,v-1); printf("%d\n",id); } } return 0; }