-
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; }
H - Tourism on Mars URAL - 2109 -LCA-线段树
猜你喜欢
转载自blog.csdn.net/BePosit/article/details/84586171
今日推荐
周排行