CF825G Tree Queries

CF825G Tree Queries

洛谷CF825G Tree Queries

题目大意

一棵树有 n n n个节点,初始时均为白色,有两种操作:

  • 1 x表示把结点 x x x染成黑色
  • 1 x表示查询 x x x到树上任意一个黑色结点的简单路径上的编号最小的结点的编号

本题强制在线。输入 t p tp tp z z z,其中 t p tp tp表示操作类型, x = ( z + l a s t )   m o d   n + 1 x=(z+last)\bmod n+1 x=(z+last)modn+1,其中 l a s t last last为上一次询问的答案,初始时 l a s t = 0 last=0 last=0

保证第一次操作为操作 1 1 1

1 ≤ n , q ≤ 1 0 6 1\leq n,q\leq 10^6 1n,q106


题解

我们把第一个染成黑色的点 t t t设为根,设查询的点为 x x x,某个被染成黑色的点为 y y y

a n s = min ⁡ y { d i s ( x , y ) } ans=\min\limits_y\{dis(x,y)\} ans=ymin{dis(x,y)},其中 d i s ( x , y ) dis(x,y) dis(x,y)表示 x → y x\to y xy路径上编号最小的点。

x x x y y y l c a lca lca z z z,则 d i s ( x , y ) = min ⁡ ( d i s ( x , z ) , d i s ( z , y ) ) dis(x,y)=\min(dis(x,z),dis(z,y)) dis(x,y)=min(dis(x,z),dis(z,y))

那么 a n s = min ⁡ y { min ⁡ ( d i s ( x , z ) , d i s ( z , y ) ) } ans=\min\limits_y\{\min(dis(x,z),dis(z,y))\} ans=ymin{min(dis(x,z),dis(z,y))}

因为 d i s ( t , x ) ≤ d i s ( x , z ) dis(t,x)\leq dis(x,z) dis(t,x)dis(x,z),所以 d i s ( x , z ) dis(x,z) dis(x,z)肯定会被 d i x ( t , x ) dix(t,x) dix(t,x)覆盖,那么 a n s = min ⁡ ( d i s ( t , x ) , min ⁡ y { d i s ( z , y ) } ) ans=\min(dis(t,x),\min\limits_y\{dis(z,y)\}) ans=min(dis(t,x),ymin{dis(z,y)})

我们继续推式子。 min ⁡ ( d i s ( t , x ) , d i s ( z , y ) ) = min ⁡ ( d i s ( t , z ) , d i s ( z , x ) , d i s ( z , y ) ) = min ⁡ ( d i s ( t , x ) , d i s ( t , y ) ) \min(dis(t,x),dis(z,y))=\min(dis(t,z),dis(z,x),dis(z,y))=\min(dis(t,x),dis(t,y)) min(dis(t,x),dis(z,y))=min(dis(t,z),dis(z,x),dis(z,y))=min(dis(t,x),dis(t,y)),所以 a n s = min ⁡ ( d i s ( t , x ) , min ⁡ y { d i s ( t , y ) } ) ans=\min(dis(t,x),\min\limits_y\{dis(t,y)\}) ans=min(dis(t,x),ymin{dis(t,y)})

也就是说,我们只需要用 d f s dfs dfs求出 t t t到每个点 x x x d i s ( t , x ) dis(t,x) dis(t,x),然后维护 min ⁡ y { d i s ( t , y ) } \min\limits_y\{dis(t,y)\} ymin{dis(t,y)}即可。

时间复杂度为 O ( n + q ) O(n+q) O(n+q)

code

#include
using namespace std;
const int N=1000000;
int n,q,rt,tmp,ans,tot=0,d[2*N+5],l[2*N+5],r[N+5],dis[N+5];
void add(int xx,int yy){
	l[++tot]=r[xx];d[tot]=yy;r[xx]=tot;
}
void dfs(int u,int fa){
	for(int i=r[u];i;i=l[i]){
		if(d[i]==fa) continue;
		dis[d[i]]=min(dis[u],d[i]);
		dfs(d[i],u);
	}
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1,x,y;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	scanf("%*d%d",&rt);--q;
	tmp=rt=(rt+ans)%n+1;
	dis[rt]=rt;dfs(rt,0);
	for(int i=1,tp,x;i<=q;i++){
		scanf("%d%d",&tp,&x);
		x=(x+ans)%n+1;
		if(tp==1) tmp=min(tmp,dis[x]);
		else printf("%d\n",ans=min(tmp,dis[x]));
	}
	return 0;
}

你可能感兴趣的:(题解,题解,c++)