zoukankan      html  css  js  c++  java
  • Hihocoder 最近公用祖先三 在线LCA

    在线的LCA算法,dfs遍历整棵树,对于每个点出现的时候都插入到数组中,然后查询两个点的lca就是两个点在数组中最后出现位置间的dep值最小的点,就转化为链上的RMQ问题了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <bitset>
    #include <queue>
    #include <stack>
    #include <string>
    #include <iostream>
    #include <cmath>
    #include <climits>
    
    using namespace std;
    const int maxn = 1e5 + 10;
    int head[maxn], nxt[maxn << 1], v[maxn << 1];
    int rpos[maxn], n, Q, cnt, ecnt;
    map<string, int> mp;
    map<int, string> smp;
    char name1[1024], name2[1024];
    
    struct Node {
    	int dep, id;
    	bool operator < (const Node &x) const {
    		return dep < x.dep;
    	}
    };
    
    Node val[maxn << 1], minv[maxn << 1][30];
    
    void adde(int uu, int vv) {
    	v[ecnt] = vv; nxt[ecnt] = head[uu]; head[uu] = ecnt++;
    }
    
    int getid(char *str) {
    	if(mp.count(str) == 0) {
    		int mpz = mp.size();
    		mp[str] = mpz + 1;
    		smp[mpz + 1] = str;
    		return mpz + 1;
    	}
    	return mp[str];
    }
    
    void dfs(int now, int fa, int dep) {
    	val[++cnt].dep = dep; val[cnt].id = now;
    	for(int i = head[now]; ~i; i = nxt[i]) if(v[i] != fa) {
    		dfs(v[i], now, dep + 1);
    		val[++cnt].dep = dep; val[cnt].id = now;
    	}
    	rpos[now] = cnt;
    }
    
    void initRMQ() {
    	for(int i = 1; i <= cnt; i++) {
    		minv[i][0] = val[i];
    	}
    	for(int j = 1; (1 << j) <= cnt; j++) {
    		for(int i = 1; i + (1 << j) - 1 <= cnt; i++) {
    			minv[i][j] = min(minv[i][j - 1], minv[i + (1 << (j - 1))][j - 1]);
    		}
    	}
    }
    
    Node query(int l, int r) {
    	int k = 0;
    	while((1 << (k + 1)) <= r - l + 1) k++;
    	return min(minv[l][k], minv[r - (1 << k) + 1][k]);
    }
    
    int main() {
    	memset(head, -1, sizeof(head));
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++) {
    		scanf("%s%s", name1, name2);
    		int a = getid(name1), b = getid(name2);
    		adde(a, b); adde(b, a);
    	}
    	dfs(1, -1, 0);
    	initRMQ();
    	scanf("%d", &Q);
    	while(Q--) {
    		scanf("%s%s", name1, name2);
    		int a = getid(name1), b = getid(name2);
    		a = rpos[a]; b = rpos[b];
    		if(a > b) swap(a, b);
    		Node ret = query(a, b);
    		puts(smp[ret.id].c_str());
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    C学习笔记-gcc
    C学习笔记-makefile
    C学习笔记-makefile
    C学习笔记-基础数据结构与算法
    上下左右居中 无固定高的div
    Touch事件 移动端touch触摸事件
    让更多浏览器支持html5元素的简单方法
    跨子域的iframe高度自适应
    10进制转16进制,16进制转10进制,随机出一个6位十六进制颜色值
    ajax原理和XmlHttpRequest对象
  • 原文地址:https://www.cnblogs.com/rolight/p/4065995.html
Copyright © 2011-2022 走看看