码迷,mamicode.com
首页 > 其他好文 > 详细

lca转RMQ

时间:2015-09-24 22:46:51      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

这个博客写得好

 

  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\n",query(u,v));
103         }
104     }
105     return 0;
106 }

 

lca转RMQ

标签:

原文地址:http://www.cnblogs.com/justPassBy/p/4836604.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!