zoukankan      html  css  js  c++  java
  • HDU 5266 pog loves szh III(区间LCA)

    题目链接 pog loves szh III

    题意就是  求一个区间所有点的$LCA$。

    我们把$1$到$n$的$DFS$序全部求出来……然后设$i$的$DFS$序为$c[i]$,$pc[i]$为$c[i]$的反函数。

    区间的$LCA$其实就是,$DFS$序最大和最小的两个点的$LCA$。

    (话说$2017$女生赛里面有一题要用的结论和这题的差不多)

    然后求出区间的$DFS$序最大值$x$和最小值$y$。

    然后求一下$LCA(pc[x],pc[y])$即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const int N = 300010;
    const int A = 21;
    
    int c[N];
    int deep[N];
    int f[N][A], g[N][A], st[N][A];
    vector <int> v[N];
    int ti;
    int n, q;
    int pc[N];
    
    void ST(){
    	rep(i, 1, n) f[i][0] = c[i];
    	rep(j, 1, 20) rep(i, 1, n)
    		if ((i + (1 << j) - 1) <= n) f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
    
    	rep(i, 1, n) g[i][0] = c[i];
    	rep(j, 1, 20) rep(i, 1, n)
    		if ((i + (1 << j) - 1) <= n) g[i][j] = max(g[i][j - 1], g[i + (1 << (j - 1))][j - 1]);
    }
    
    inline int solvemin(int l, int r){
    	int k = (int)log2((double)(r - l + 1));
    	return min(f[l][k], f[r - (1 << k) + 1][k]);
    
    }
    
    inline int solvemax(int l, int r){
    	int k = (int)log2((double)(r - l + 1));
    	return max(g[l][k], g[r - (1 << k) + 1][k]);
    }
    
    
    void dfs(int x, int fa, int dep){
    	c[x] = ++ti; pc[ti] = x;
    	deep[x] = dep;
    	if (fa){
    		st[x][0] = fa;
    		for (int i = 0; st[st[x][i]][i]; ++i) st[x][i + 1] = st[st[x][i]][i];
    	}
    
    	for (auto u : v[x]){
    		if (u == fa) continue;
    		dfs(u, x, dep + 1);
    	}
    }
    
    int LCA(int a, int b){
    	if (deep[a] < deep[b]) swap(a, b);
    	for (int i = 0,  delta = deep[a] - deep[b]; delta; delta >>= 1, ++i) if (delta & 1) a = st[a][i];
    	if (a == b) return a;
    	dec(i, 19, 0) if (st[a][i] != st[b][i]) a = st[a][i], b = st[b][i];
    	return st[a][0];
    }
    
    int main(){
    
    	while (~scanf("%d", &n)){
    		rep(i, 0, n + 1) v[i].clear();
    		memset(c, 0, sizeof c);
    		ti = 0;
    		rep(i, 2, n){
    			int x, y;
    			scanf("%d%d", &x, &y);
    			v[x].push_back(y);
    			v[y].push_back(x);
    		}
    
    		memset(st, 0, sizeof st);
    		memset(f, 0, sizeof f);
    		memset(g, 0, sizeof g);
    		dfs(1, 0, 0);
    		ST();
    		for (scanf("%d", &q); q--; ){
    			int x, y;
    			scanf("%d%d", &x, &y);
    			printf("%d
    ", LCA(pc[solvemax(x, y)], pc[solvemin(x, y)]));
    
    		}
    	}
    
    
    	return 0;
    }
    
  • 相关阅读:
    堆排序算法
    二叉树的创建、遍历(递归和非递归实现)、交换左右子数、求高度(c++实现)
    hdoj1010 奇偶剪枝+DFS
    常见排序算法c++总结
    B
    C
    D
    E
    G
    F
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7270542.html
Copyright © 2011-2022 走看看