zoukankan      html  css  js  c++  java
  • lca转RMQ

    这个博客写得好

      1 #include <stdio.h>
      2 #include <vector>
      3 #include <string.h>
      4 using namespace std;
      5 const int N = 100000;
      6 
      7 /*
      8     lca 转RMQ
      9 
     10     询问u和v的lca
     11     我们保存树的遍历序列,那么只要在序列中找到第一次出现u和第一次出现v的位置
     12     然后RMQ该区间深度最小的那个点就是u和v的lca了
     13 
     14     那么要保存每个点首次出现的位置
     15     还要保存遍历序列的dep序列,然后RMQ dep序列得到哪一位置的dep最小
     16     然后映射为结点
     17 */
     18 
     19 vector<int> g[N];
     20 int total;
     21 int id[N];
     22 int dep[N];
     23 int ref[N];
     24 int dp[N][30];
     25 int pos[N][30];
     26 void dfs(int u, int fa, int d)
     27 {
     28     id[u] = ++total;
     29     dep[total] = d;//
     30     ref[total] = u;
     31     for(int i=0;i<g[u].size(); ++i)
     32     {
     33         int v = g[u][i];
     34         if(v==fa)continue;
     35         dfs(v,u,d+1);
     36         dep[++total] = d;//回来
     37         ref[total] = u;
     38     }
     39     
     40 }
     41 
     42 void init()
     43 {
     44     int n = total;
     45     for(int i=1;i<=n;++i)
     46         dp[i][0] = i;
     47     
     48     
     49     for(int j=1;(1<<j)<=n;++j)
     50     {
     51         for(int i=1;i+(1<<j)-1<=n;++i)
     52         {
     53             int a = dp[i][j-1];
     54             int b = dp[i+(1<<(j-1))][j-1];
     55             if(dep[a] < dep[b])
     56                 dp[i][j] = a;
     57             else
     58                 dp[i][j] = b;
     59         }
     60     }
     61 }
     62 int query(int u, int v)
     63 {
     64     if(id[u] > id[v])
     65         swap(u,v);
     66     int L = id[u];
     67     int R = id[v];
     68     int k = 0;
     69     while(1<<(k+1)<=R-L+1)k++;
     70     int a = dp[L][k];
     71     int b = dp[R-(1<<k)+1][k];
     72     if(R[a]<R[b])
     73     {
     74         return ref[a];
     75     }
     76     else
     77         return ref[b];
     78 }
     79 int main()
     80 {
     81     int n;
     82     while(scanf("%d",&n)!=EOF)
     83     {
     84         for(int i=1;i<=n;++i)
     85             g[i].clear();
     86         int u,v;
     87         for(int i=1;i<n;++i)
     88         {
     89             scanf("%d%d",&u,&v);
     90             g[u].push_back(v);
     91             g[v].push_back(u);
     92         }
     93         total = 0;
     94         dep[1] = 1;
     95         dfs(1,-1,1);
     96         init();
     97         int m;
     98         scanf("%d",&m);
     99         while(m--)
    100         {
    101             scanf("%d%d",&u,&v);
    102             printf("%d
    ",query(u,v));
    103         }
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    一些数学证明
    重头再来
    二次函数传参
    神经网络
    准备写点随笔了
    如何做出响应式的页面 (转)
    自适应,响应式,viewport总结
    edm邮件制作规范
    博客园blog模板整理
    git 常用的命令
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4836604.html
Copyright © 2011-2022 走看看