在线LCA

const int MAXN = 10010;
const int MAXM = 10010;  

struct N
{
    int v,w,next;
}edge[MAXM*2];
int Top;
int head[MAXN];
int MAXSIZE;
int dep[MAXN];
int seq[MAXN*2];
int R[MAXN];  

struct ST
{
    int dep,point;
    bool operator < (const ST &A) const
    {
        return dep < A.dep;
    }
}st[MAXN*8];
  //若为无向图则w = 1。
void Link(int u,int v,int w)
{
    edge[Top].v = v;
    edge[Top].w = w;
    edge[Top].next = head[u];
    head[u] = Top++;
}  

void Init()
{
    memset(head,-1,sizeof(head));
    Top = 0;
    MAXSIZE = 0;
}  

void InitDep(int s,int pre = -1,int d = 0)
{
    R[s] = ++MAXSIZE;
    seq[MAXSIZE] = s;
    dep[s] = d;  

    for(int p =  head[s]; p != -1; p = edge[p].next)
    {
        if(edge[p].v != pre)
        {
            InitDep(edge[p].v,s,d+edge[p].w);
            seq[++MAXSIZE] = s;
        }
    }
}  

void InitST(int site,int l,int r)
{
    if(l == r)
    {
        st[site].dep = dep[seq[l]];
        st[site].point = seq[l];
        return ;
    }  

    int mid = (l+r)>>1;  

    InitST(site<<1,l,mid);
    InitST(site<<1|1,mid+1,r);  

    st[site] = st[site<<1].dep < st[site<<1|1].dep ? st[site<<1] : st[site<<1|1];
}  

ST QueryLCA(int site,int L,int R,int l,int r)
{
    if(L == l && R == r)
        return st[site];  

    int mid = (L+R)>>1;  

    if(r <= mid)
        return QueryLCA(site<<1,L,mid,l,r);
    else if(mid < l)
        return QueryLCA(site<<1|1,mid+1,R,l,r);  

    return min(QueryLCA(site<<1,L,mid,l,mid),QueryLCA(site<<1|1,mid+1,R,mid+1,r));  

} 

时间: 2024-11-09 02:22:20

在线LCA的相关文章

hdu3078 建层次树+在线LCA算法+排序

题意:n个点,n-1条边构成无向树,每个节点有权,Q次询问,每次或问从a->b的最短路中,权第k大的值,/或者更新节点a的权, 思路:在线LCA,先dfs生成树0,标记出层数和fa[](每个节点的父亲节点).在对每次询问,走一遍一次公共祖先路上 的权,保持,快排.n*logn*q #include<iostream> //187MS #include<algorithm> #include<cstdio> #include<vector> using

POJ 1330 Nearest Common Ancestors (在线LCA转RMQ)

题目地址:POJ 1330 在线LCA转RMQ第一发.所谓在线LCA,就是先DFS一次,求出遍历路径和各个点深度,那么求最近公共祖先的时候就可以转化成求从u到v经过的点中深度最小的那个. 纯模板题. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h&g

hdu 5266 pog loves szh III 在线lca+线段树区间优化

题目链接:hdu 5266 pog loves szh III 思路:因为它查询的是区间上的lca,所以我们需要用在线lca来处理,达到单点查询的复杂度为O(1),所以我们在建立线段树区间查询的时候可以达到O(1*nlgn)的时间复杂度 ps:因为栈很容易爆,所以.....你懂的 -->#pragma comment(linker, "/STACK:1024000000,1024000000") /*****************************************

Hihocoder 最近公用祖先三 在线LCA

在线的LCA算法,dfs遍历整棵树,对于每个点出现的时候都插入到数组中,然后查询两个点的lca就是两个点在数组中最后出现位置间的dep值最小的点,就转化为链上的RMQ问题了. #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <set> #include <bitset> #include <queue> #i

#7 div1 A Breadth-First Search by Foxpower 在线LCA(倍增),模拟

A - Breadth-First Search by Foxpower Time Limit:2000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Submit Status Description A - Breadth-First Search by Foxpower Problem Statement Fox Ciel went to JAG Kingdom by bicycle, but she forgot

POJ 1470 Closest Common Ancestors (在线LCA转RMQ)

题目地址:POJ 1470 LCA模板题..输入有点坑,还有输入的第一个结点不一定是根节点. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include

HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)

题目地址:HDU 5266 这题用转RMQ求LCA的方法来做的非常简单,只需要找到l-r区间内的dfs序最大的和最小的就可以,那么用线段树或者RMQ维护一下区间最值就可以了.然后就是找dfs序最大的点和dfs序最小的点的最近公共祖先了. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #inc

POJ 1986 Distance Queries (在线LCA转RMQ)

题目地址:POJ 1986 纯模板题.输入的最后一个字母是多余的,完全不用管.还有注意询问的时候有相同点的情况. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set>

HDU 4409 Family Name List --乱搞、LCA

题意: 给出一些名字,名字间有父子关系,有三种操作: 1.按祖先到后代,兄弟间按字典序由小到大排序,然后输出 2.求某个节点的兄弟节点有多少个,包括自己(注意,根节点的兄弟节点是1) 3.求节点a和b的公共祖先 (注意:如果公共祖先是a或b,必须要输出其父亲,与传统的LCA可以是自己不同) 解法: 先把整棵树整理出来,son[u]表示u的儿子个数,用来求兄弟个数, fa[u]表示父亲,Gson存储儿子的标号,关于排序的问题,先读入所有名字,然后排个序哈希一下,使字典序小的节点标号一定小,那么直接