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 namespace std;
int n,q;
int w[90000];
vector<vector<int> >e(160100);
int lev[80010];int vis[80010];
int fa[80010];
void dfs_getlev(int u)       //dfs
{
    for(int i=0;i<e[u].size();i++)
    {
        int v=e[u][i];
        if(!vis[v])
        {
            vis[v]=1;
            lev[v]=lev[u]+1;
            fa[v]=u;
            dfs_getlev(v);
        }
    }
}
bool my(int a,int b)
{
     return a>b;
}
int find_lca(int k,int a,int b)   //在线lca,按层次向上走。
{
    vector<int> ans;
    if(lev[a]>lev[b])
    {
        int temp=a;a=b;b=temp;
    }
    while(lev[b]>lev[a])
    {
        ans.push_back(w[b]);
        b=fa[b];
    }
    while(a!=b)
    {
        ans.push_back(w[b]);
        ans.push_back(w[a]);
        a=fa[a];
        b=fa[b];
    }
     ans.push_back(w[b]);
   if(k>ans.size()) return -1;
   sort(ans.begin(),ans.end(),my);
   return   ans[k-1];
}
int main()
{
    cin>>n>>q;
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
    int ta,tb;
    for(int i=0;i<n-1;i++)
    {
          scanf("%d%d",&ta,&tb);
          e[ta].push_back(tb);
          e[tb].push_back(ta);
    }
    vis[1]=lev[1]=1;
    dfs_getlev(1);
    int k,a,b;
    while(q--)
    {
        scanf("%d%d%d",&k,&a,&b);
        if(k>0)
        {
            int anss =find_lca(k,a,b);
            if(anss!=-1)
              printf("%d\n",anss);
            else
              printf("invalid request!\n");
        }
        else
        {
            w[a]=b;
        }
    }
    return 0;
}

hdu3078 建层次树+在线LCA算法+排序,布布扣,bubuko.com

时间: 2024-12-12 10:38:16

hdu3078 建层次树+在线LCA算法+排序的相关文章

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

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

js 数组排序和算法排序

1.算法排序 a.插入排序 var arr = [23,34,3,4,23,44,333,444]; var arrShow = (function insertionSort(array){ if(Object.prototype.toString.call(array).slice(8,-1) ==='Array'){ for (var i = 1; i < array.length; i++) { var key = array[i]; var j = i - 1; while (j >

LCA 算法学习 (最近公共祖先)poj 1330

poj1330 在求解最近公共祖先为问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,处理技巧就是在回溯到结点u的时候,u的子树已经遍历,这时候才把u结点放入合并集合中,这样u结点和所有u的子树中的结点的最近公共祖先就是u了,u和还未遍历的所有u的兄弟结点及子树中的最近公共祖先就是u的父亲结点.这样我们在对树深度遍历的时候就很自然的将树中的结点分成若干的集合,两个集合中的所属不同集合的任意一对顶点的公共祖先都是相同的,也就是说这两个集合的最近公共祖先只有一个.时间复杂度为O(n+q

数据结构与算法 - 排序与搜索

排序与搜索 排序算法(英语:Sorting algorithm)是一种能将一串数据依照特定顺序进行排列的一种算法. 1.冒泡排序 冒泡排序(英语:Bubble Sort)是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. 冒泡排序算法的运作如下: 比较相邻的元素.如果第一个比第二个大(升序),就

洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

洛谷题目传送门 %%%天平巨佬和山楠巨佬%%% 他们的题解 思路分析 具体思路都在两位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 首先kruskal把最小生成树弄出来,因为要求次小生成树.至于为什么次小一定只在最小的基础上改变了一条边,我也不会证......打表找规律大法好 剩下的可以有一堆数据结构来维护最大值和次大值(原理两位巨佬都讲清楚了,这里只分析一下算法的优劣) 倍增+LCA 山楠巨佬的做法,我也写了这一种.复杂度\(O(MlogM(kruscal)+MlogN(

数据结构与算法 介绍以及常见的算法排序

介绍 数据结构: 计算机存储,组织数据的结构.指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成. 线性数据结构:数组,链表 应用:队列 栈 非线性数据结构:树,图 算法: 对数据结构中数据的操作 常见的算法排序 low B三件套 #冒泡排序 #时间复杂度:O(n2) #空间复杂度:O(1) def bubble_sort(li): for i in range(len(li)-1): flag = False for j in range(len(li)-i-1):

树常见的算法操作

树是数据结构中很重要的一部分,也是各大公司面试常考部分. 继树的各种遍历算法之后,今天又整理一下树的常见算法操作. 本文包括: 1.求节点的最近公共祖先 2.树的序列化与反序列化 3.已知先序遍历和中序遍历构造二叉树 4.已知中序遍历和后序遍历构造二叉树 1.求节点最近的公共祖先 此题不同的要求有不同的解法 如果已知树中的每一个结点有指向父节点的指针: 思路:从给定节点遍历到根节点,当父节点相等时返回. 解法1 private ArrayList<TreeNode> getPath2Root(