`

Hihocoder --- 17周 LCA的在线算法

 
阅读更多
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <cstdlib>
#include <stdio.h>

using namespace std;

string x[200005];
int weight[200005];
int segtree[200005][20];
string name[200005][20];
int mycount = 0, mleft = 0, mright = 0;
map<string, int> last;

template <class T>
class Node{
/*
 *  This is a Tree Node class.
*/
    public:
        T field, parent;
		int depth;
        vector<T> son;

		Node(){
			field = "";
			depth = 0;
			son.clear();
			parent = "";
		}

        Node(T myfield){
            field = myfield;
			depth = 0;
            son.clear();
            parent = "";
        }

        void add_child(T child){
            son.push_back(child);
        }

        void set_parent(T sparent){
            parent = sparent;
        }
};

template <class T>
class GenTree{
    public:
        Node<T> *root;
        map<T, Node<T>* > nodes;

		GenTree(){}

        GenTree(T root_field){
            root = new Node<T>(root_field);
            root->parent = root_field;
            nodes.insert(pair<T, Node<T>* >(root_field, root));
        }

        Node<T>* add_node(T field, T parent = ""){
            Node<T> *node = new Node<T>(field);

            nodes[field] = node;
            if (parent!= ""){
                nodes[parent]->add_child(field);
                node->parent = parent;
            }
			else
				node->parent = field;

            return node;
        }

		void dfs(T field, int depth){
			x[mycount++] = field;
			nodes[field]->depth = depth;
			int size = nodes[field]->son.size();
			if (size != 0){
				for (int i=0; i<size; i++){
					T cur_son = nodes[field]->son[i];
					dfs(cur_son, depth + 1);
					x[mycount++] = field;
				}
			}
			last[field] = mycount;
		}
};

int cal_pow(int x, int y){
	if (y == 1)
		return x;
	else if (y == 0)
		return 1;
	if (y % 2 == 0){
		int temp_value = cal_pow(x, y/2);
		return temp_value * temp_value;
	}
	else{
		int temp_value = cal_pow(x, (y-1)/2);
		return temp_value * temp_value * x;
	}
}

int findmax(int len){
	int count = -1;
	while (len > 0){
		count++;
		len = (len >> 1);
	}
	return count;
}

int main()
{
    GenTree<string> mytree;
	int n, m, len, maxT, templen;
	string name1, name2, root;

	cin>>n;
	for (int i=0; i<n; i++){
		cin>>name1>>name2;
		
		if (i==0){
			root = name1;
			mytree.add_node(name1);
			mytree.add_node(name2, name1);
		}
		else
			mytree.add_node(name2, name1);
	}

	mytree.dfs(root, 1);
	
	for (int j=0; j<=findmax(2*n+1); j++)
		for (int i=1; i<=2*n+1; i++) {
			len = cal_pow(2, j);
			if (j == 0){
				segtree[i][j] = mytree.nodes[x[i-1]]->depth;
				name[i][j] = x[i-1];
			}
			else if ((i + len/2) <= (2*n+1)){
				if (segtree[i][j-1] > segtree[i+len/2][j-1]){
					segtree[i][j] = segtree[i+len/2][j-1];
					name[i][j] = name[i+len/2][j-1];
				}else{
					segtree[i][j] = segtree[i][j-1];
					name[i][j] = name[i][j-1];
				}
			}
		}


	cin>>m;
	for (int i=0; i<m; i++){
		cin>>name1>>name2;
		if (last[name1] > last[name2]){
			mleft = last[name2];
			mright = last[name1];
		}else{
			mleft = last[name1];
			mright = last[name2];
		}
		len = mright - mleft + 1;
		maxT = findmax(len);
		templen = cal_pow(2, maxT);
		if (segtree[mleft][maxT] > segtree[mright - templen + 1][maxT])
			cout<<name[mright - templen + 1][maxT]<<endl;
		else
			cout<<name[mleft][maxT]<<endl;
	}
	
    return 0;
}

 

分享到:
评论

相关推荐

    Tarjan 的 LCA 算法

    **Tarjan的LCA算法详解** 最近公共祖先(Lowest Common Ancestor,简称LCA)是图论中的一个重要概念,特别是在树形结构中。在树中,两个节点的最近公共祖先指的是距离根节点最近的那个同时是这两个节点的祖先的节点...

    郭华阳《RMQ与LCA问题》

    **RMQ(Range Minimum Query)与LCA(Lowest Common Ancestor)问题**是图论与数据结构领域中的两个重要概念,广泛应用于算法设计和优化。这篇由郭华阳所著的国家队论文深入探讨了这两个问题及其解决方案。 **RMQ...

    Pascal LCA 倍增法详解及代码

    解决LCA问题的方法主要有两类:在线算法和离线算法。在线算法需要在每次询问时快速回答,而离线算法则先一次性处理所有询问。朴素的在线算法时间复杂度较高,可达O(n),在大量询问的情况下效率较低。 本文介绍的是...

    LCA的tarjan算法

    对于LCA问题,有不少解法,这儿提供了tarjan算法,这是一种离线算法,读入所有输入然后一并处理,并且利用并查集的思想,从根节点开始DFS,对每一个DFS的节点,先把他的父亲节点指向本身,没访问完一个子节点,然后...

    linux-conf-au-2019-epaper-badge:lca2019的我的IoT徽章

    【标题】"Linux Conf AU 2019 E-Paper Badge: LCA2019的IoT徽章"是一个项目,它展示了在Linux Conf AU 2019(一个年度Linux和技术会议)上使用的物联网(IoT)电子纸显示徽章。这个徽章不仅是一个标识符,更是一个小型...

    LCA算法的讲解(非常详细)

    【LCA算法详解】 最近公共祖先(Lowest Common Ancestor,简称LCA)问题在图论和算法领域中是一个常见的问题,特别是在树形结构的数据结构中。它涉及到找到树中两个给定节点的最近公共祖先,即离这两个节点最近的...

    LCA-AW2.2.zip

    在【LCA-AW2.2.zip】这个压缩包中,我们可以找到名为“LCA-AW2.2”的程序或更新文件。这可能是该软件的最新版本,提供与官网同步的功能和性能。用户可以下载并安装此文件,将LCA软件设置为本地接口,这样可以避免...

    算法之LCA与RMQ问题1

    为了提高效率,可以采用在线算法如DFS+ST(深度优先搜索+稀疏表)或离线算法如Tarjan算法。DFS+ST方法通过深度优先遍历构建E数组,并计算R数组以确定访问顺序,从而在O(logn)时间内找到LCA。Tarjan算法则是通过松弛...

    lca.rar_LCA

    在IT领域,特别是数据结构和算法的设计中,"最近公共祖先"(Lowest Common Ancestor,简称LCA)是一个常见的问题。这个问题出现在许多场景中,比如计算机科学中的树形结构处理,生物信息学中的基因进化分析等。最近...

    Tarjan应用LCA

    标题中的“Tarjan应用LCA”指的是在图论和数据结构领域中,使用Tarjan算法来解决最近公共祖先(Least Common Ancestor, LCA)问题。最近公共祖先是指在一棵树中,两个节点的共同祖先中离根节点最远的一个。LCA问题在...

    lca_one_layer.zip_LCA_LCA算法_图像分析_图像基元_基元 matlab

    LCA (Lobe Component Analysis) Lobe成分分析法,图像基元的特征检测算法。

    第4章 倍增求LCA-2019-12-05.pdf

    总之,文档“第4章 倍增求LCA-2019-12-05.pdf”应是一份专门讲述如何通过倍增法高效求解树上最近公共祖先问题的教材,包含了理论知识和实际应用例题,适合学习高级树算法和准备算法竞赛的学生。

    RMQ与LCA ACM必备

    RMQ分为在线算法和离线算法。 1. **在线算法**: 在线算法需要在接收到查询时立即给出答案。预处理阶段可能需要较长时间,但之后每次回答查询的速度非常快。例如,简单的动态规划方法虽然能实现O(1)的查询时间,但...

    LCA (最近公共祖先) Tarjan & 倍增

    LCA Tarjan: 实现原理 理解:离线算法,建好树后再查询,一次DFS 吧所有查询解决完。 时间复杂度:O(n+q); n个点 q次询问 补一下:链式向前星,并查集 ,Tarjan 代码 #include #include #include #include #...

    ACM图论模板合集.pdf

    图论--LCA--树上倍增法(在线) 图论--LCA--在线RMQ ST 最小环: 图论--最小环--Floyd模板 树的直径: 图论--树的直径--DFS+树形DP模板 树的重心: 图论--树的重心(DFS) 模板 生成树: ...

Global site tag (gtag.js) - Google Analytics