列表

详情


NC233098. 树上博弈

描述

给定一棵 n 个点的树,定义一个两个人的博弈过程如下。

定义一个变量 x,初始值为 k,其中 k 是一个给定值,初始有一个石子,位置在 p

两人轮流操作:

找到 z,满足 ,其中 dis(x,y) 表示两个点在树上的最短路径长度,若不存在这样的 z,则判负,然后令

你需要支持:

1. 在树上加入一个新的点。

2. 给定 k,p,判断是否先手必胜。

输入描述

第一行两个正整数 

之后 n-1 行,每行两个整数 x,y,表示树上一条 x,y 之间的双向边。

之后 q 行,每行形如

若第一个数为 1,令当前点数为 N,新建一个编号为 的点,并新建一条与 x 相连的边。

否则表示一次询问。

输出描述

对于每一组询问,输出 1 表示存在必胜策略,否则输出 0 表示没有。

示例1

输入:

5 4
1 2
1 3
1 4
2 5
1 2
2 3 3
2 2 3
2 0 6

输出:

0
1
1

说明:

对于第一个询问,先手没有可以第一步走出的点。

对于第二个询问,先手可以第一步走到点 6,此时后手无点可走。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 1157ms, 内存消耗: 94316K, 提交时间: 2022-02-19 08:26:16

#include<bits/stdc++.h>
#define MAXN 800005
using namespace std;

int n,Q;
int dep[MAXN],f[MAXN][25];
vector<int>G[MAXN];
void dfs(int now , int fa){
	f[now][0] = fa , dep[now] = dep[fa] + 1;
	for(auto v : G[now]){
		if(v == fa)continue;
		dfs(v , now);
	}
}

int lca(int x , int y){
	if(dep[x] < dep[y])swap(x , y);
	int dx = dep[x] - dep[y];
	for(int i = 0 ; i <= 20 ; i++)if(dx & (1ll << i))x = f[x][i];
	if(x == y)return x;
	for(int i = 20 ; i >= 0 ; i--){
		if(f[x][i] != f[y][i])x = f[x][i] , y = f[y][i];
	}
	return f[x][0];
}

int dis(int x , int y){
	return dep[x] + dep[y] - 2 * dep[lca(x , y)];
}

int main(){
	scanf("%d%d" , &n , &Q);int x,y;
	for(int i = 1 ; i < n ; i++){
		scanf("%d%d" , &x , &y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs(1 , 1);
	for(int j = 1 ; j <= 20 ; j++)
		for(int i = 1 ; i <= n ; i++)
			f[i][j] = f[f[i][j - 1]][j - 1];
	int tp;
	int u = 1,v = 1,maxl = 0;
	for(int i = 2 ; i <= n ; i++)if(dis(u , i) > dis(u , v))v = i;
	for(int i = 1 ; i <= n ; i++)if(dis(i , v) > dis(u , v))u = i;
	maxl = dis(u , v);
	while(Q--){
		scanf("%d" , &tp);
		if(tp == 1){
			scanf("%d" , &x);
			n++ , f[n][0] = x , dep[n] = dep[x] + 1;
			for(int j = 1 ; j <= 20 ; j++)f[n][j] = f[f[n][j - 1]][j - 1];
			if(dis(u , v) < dis(u , n))v = n;
			if(dis(u , v) < dis(v , n))u = n;
			maxl = dis(u , v);
		}
		else{
			scanf("%d%d" , &x , &y);
			//判断与直径相关大小
			int A,B;
			A = dis(u , y) , B = dis(v , y);
			if(A < B)swap(A , B) , swap(u , v);
			int C , D;
			C = maxl - A , D = maxl - C;
			if(D - C > x)cout<<1<<endl;
			else cout<<0<<endl;
		}
	}
}

上一题