牛客多校8 J-Tree

原题链接
树上两点之间的路径是唯一的,我们发现,当有人脱离了两者之间的路径时,他所走的步数不会被对方所干预(双方已经毫无关系了),故可以对抗搜索,当有一方离开两点路径之时,直接统计答案。
详情见代码:

/*
牛客多校8-J
对抗搜索,剪枝,rmq表预处理。
思路:
dfs1预处理出s到t 的唯一路径
dfs2预处理出s到t唯一路径上每一点下悬挂的最长路径,用path[i]存储。
path1[i]表示s选择在i点离开唯一路径时,所获得的最多操作步数 
path2[i]表示t选择在i点离开唯一路径时,所获得的最多操作步数 
F[][], G[][] 为path1[], path2[]两数组rmq询问前的预处理数组。
max1(l, r) 表示path1[l].....path1[r]的最大值 
max2(l, r) 表示path2[l].....path2[r]的最大值
对抗搜索,分mode 0,表示s方要最优的决策,  mode 1, 表示t方要最优的决策
当状态遇到(i, j, 0)时,有2种选择:
1、s方在i点离开2者之间的路径, 则答案为path1[i]
在这之后,t方的答案就是max2(i + 1, j) //在(i + 1, j)区间中进行rmq询问。
2、进行状态(i + 1, j , 1). 
同理状态(i, j, 1); 
*/
#include <bits/stdc++.h>
using namespace std;
#define N 500005
int n, s, t, to[N << 1], nxt[N << 1], head[N], path[N << 1], inp[N], vis[N], cnt, m;
int path1[N << 1], path2[N << 1]; 
int F[20][N], G[20][N];
int max1(int l,int r) {
    int x = log2(r - l + 1);
    return max(F[x][l], F[x][r - (1 << x) + 1]);
} 
int max2(int l,int r) {
    int x = log2(r - l + 1);
    return max(G[x][l], G[x][r - (1 << x) + 1]);
}
void ae(int x,int y) {
    to[++cnt] = y, nxt[cnt] = head[x], head[x] = cnt;
}
int dfs1(int u, int t, int dep) {
	vis[u]=1;
	if(u == t) {
		path[dep] = u;
		inp[u] = 1;
		return dep;
	}
	for(int i = head[u]; i; i = nxt[i]) {
        int y = to[i];
        if(!vis[y]) {
        	int tmp = dfs1(y, t, dep + 1);
        	if(tmp) {
        		path[dep] = u;
        		inp[u] = 1;
        		return tmp;
			}
        }
    }
    return 0; 
}
int dfs2(int u, int dep) {
	vis[u] = 1; int tmp = dep;
	for(int i = head[u]; i; i = nxt[i]) {
        int y = to[i];
        if(!vis[y] && !inp[y]) {
        	tmp = max(tmp, dfs2(y, dep + 1));
        }
    }
    return tmp;
}
void init() {
	for(int i = 1; i <= m; i++) {
		F[0][i] = path1[i], G[0][i] = path2[i];	
	}
    for(int i = 1; i <= 19; i++) {
    	for(int j = 1; j + (1 << (i - 1)) <= m; j++) {
    		F[i][j] = max(F[i - 1][j], F[i - 1][j + (1 << (i - 1))]);
		}
	}
    for(int i = 1; i <= 19; i++) {
    	for(int j = 1; j + (1 << (i - 1)) <= m; j++) {
        	G[i][j] = max(G[i-1][j], G[i - 1][j + (1 << (i - 1))]);
		}
	}
}

int dfs3(int i, int j, int mode) {
	if(mode == 0) {
		int score = path1[i] - max2(i + 1, j);
		if(i + 1 < j) return max(score, -dfs3(i + 1, j, 1));
		else return score;
	}
	if(mode == 1) {
		int score = path2[j] - max1(i, j - 1);
		if(i + 1 < j) return max(score, -dfs3(i, j - 1, 0));
		else return score;
	}
}

int main() {
    scanf("%d %d %d", &n, &s, &t);
    for(int i = 1; i < n; i++) {
        int ui, vi;
        scanf("%d %d", &ui, &vi);
        ae(ui, vi); ae(vi, ui);
    }
    memset(vis,0,sizeof(vis));
    m = dfs1(s, t, 1);
    memset(vis, 0, sizeof(vis));
    for(int i = 1;i <= m; i++) {
    	path[i] = dfs2(path[i], 0);
	}
	for (int i = 1; i <= m; i++) {
		path1[i] = path[i] + i - 1;
		path2[i] = path[i] + m - i;
	}
	init();
	printf("%d\n", dfs3(1, m, 0));
    return 0;
}
posted @ 2021-08-10 17:40  Leins  阅读(93)  评论(0编辑  收藏  举报