lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs

Posted cmyg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problemnew/show/P3379

 

1.欧拉序+rmq(st)

 

  1 /*
  2 在这里,对于一个数,选择最左边的
  3 选择任意一个都可以,[left_index,right_index],深度都大于等于这个数的深度
  4 */
  5 #include <cstdio>
  6 #include <cstdlib>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <time.h>
 10 #include <string>
 11 #include <set>
 12 #include <map>
 13 #include <list>
 14 #include <stack>
 15 #include <queue>
 16 #include <vector>
 17 #include <bitset>
 18 #include <ext/rope>
 19 #include <algorithm>
 20 #include <iostream>
 21 using namespace std;
 22 #define ll long long
 23 #define minv 1e-6
 24 #define inf 1e9
 25 #define pi 3.1415926536
 26 #define E  2.7182818284
 27 const ll mod=1e9+7;//998244353
 28 const int maxn=5e5+10;
 29 
 30 struct node
 31 {
 32     int d;
 33     node *next;
 34 }*e[maxn];
 35 
 36 int s=0;
 37 
 38 ///每条边走两遍,n-1条边,走2(n-1)个点
 39 int a[maxn<<1],b[maxn<<1],f[maxn<<1][20],lef[maxn],er[20];
 40 bool vis[maxn]={0};
 41 
 42 void dfs(int d,int dep)
 43 {
 44     node* p=e[d];
 45     vis[d]=1;
 46     s++;
 47     lef[d]=s;
 48     a[s]=d;
 49     b[s]=dep;
 50     while (p)
 51     {
 52         if (!vis[p->d])
 53         {
 54             dfs(p->d,dep+1);
 55             s++;
 56             a[s]=d;
 57             b[s]=dep;
 58         }
 59         p=p->next;
 60     }
 61 }
 62 
 63 int main()
 64 {
 65     int n,q,root,x,y,i,j,k,m,d;
 66     node *p;
 67     scanf("%d%d%d",&n,&q,&root);
 68     for (i=1;i<n;i++)
 69     {
 70         scanf("%d%d",&x,&y);
 71         p=(node*) malloc (sizeof(node));
 72         p->d=y;
 73         p->next=e[x];
 74         e[x]=p;
 75 
 76         p=(node*) malloc (sizeof(node));
 77         p->d=x;
 78         p->next=e[y];
 79         e[y]=p;
 80     }
 81     dfs(root,1);
 82 
 83     m=log(s)/log(2);
 84     er[0]=1;
 85     for (i=1;i<=m;i++)
 86         er[i]=er[i-1]<<1;
 87     for (i=1;i<=s;i++)
 88         f[i][0]=i;
 89 //        f[i][0]=b[i];
 90     for (i=1;i<=m;i++)   //2^i
 91         for (j=1,k=j+er[i-1];j<=s-er[i]+1;j++,k++)  //-er[i]+1
 92             if (b[ f[j][i-1] ] < b[ f[k][i-1] ])
 93                 f[j][i]=f[j][i-1];
 94             else
 95                 f[j][i]=f[k][i-1];
 96 //            f[j][i]=min(f[j][i-1],f[j+er[i-1]][i-1]);
 97 
 98     while (q--)
 99     {
100         scanf("%d%d",&x,&y);
101         x=lef[x];
102         y=lef[y];
103         if (x>y)
104             swap(x,y);
105         d=log(y-x+1)/log(2);
106         j=y-er[d]+1;
107         if (b[ f[x][d] ] < b[ f[j][d] ])    //+1
108             printf("%d
",a[ f[x][d] ]);
109         else
110             printf("%d
",a[ f[j][d] ]);
111 //        printf("%d
",min(f[x][d],f[y-er[d]+1][d]));
112     }
113     return 0;
114 }
115 /*
116 8 100 1
117 1 2
118 1 3
119 2 4
120 2 5
121 3 6
122 5 7
123 6 8
124 
125 5 7
126 5
127 2 3
128 1
129 3 2
130 1
131 1 8
132 1
133 2 8
134 1
135 4 5
136 2
137 5 4
138 2
139 */

 

 

2.欧拉序+线段树

  1 /*
  2 在这里,对于一个数,选择最左边的
  3 选择任意一个都可以,[left_index,right_index],深度都大于等于这个数的深度
  4 */
  5 #include <cstdio>
  6 #include <cstdlib>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <time.h>
 10 #include <string>
 11 #include <set>
 12 #include <map>
 13 #include <list>
 14 #include <stack>
 15 #include <queue>
 16 #include <vector>
 17 #include <bitset>
 18 #include <ext/rope>
 19 #include <algorithm>
 20 #include <iostream>
 21 using namespace std;
 22 #define ll long long
 23 #define minv 1e-6
 24 #define inf 1e9
 25 #define pi 3.1415926536
 26 #define E  2.7182818284
 27 const ll mod=1e9+7;//998244353
 28 const int maxn=5e5+10;
 29 
 30 struct node
 31 {
 32     int d;
 33     node *next;
 34 }*e[maxn];
 35 
 36 int s=0;
 37 
 38 ///每条边走两遍,n-1条边,走2(n-1)个点
 39 int a[maxn<<1],b[maxn<<1],lef[maxn],f[maxn<<3];
 40 bool vis[maxn]={0};
 41 int num=0;
 42 
 43 void dfs(int d,int dep)
 44 {
 45     node* p=e[d];
 46     vis[d]=1;
 47     s++;
 48     lef[d]=s;
 49     a[s]=d;
 50     b[s]=dep;
 51     while (p)
 52     {
 53         if (!vis[p->d])
 54         {
 55             dfs(p->d,dep+1);
 56             s++;
 57             a[s]=d;
 58             b[s]=dep;
 59         }
 60         p=p->next;
 61     }
 62 }
 63 
 64 void build(int index,int l,int r)
 65 {
 66     if (l==r)
 67         f[index]=++num;
 68     else
 69     {
 70         int m=(l+r)>>1;
 71         build(index<<1,l,m);
 72         build(index<<1|1,m+1,r);
 73         if (b[f[index<<1]]<b[f[index<<1|1]])
 74             f[index]=f[index<<1];
 75         else
 76             f[index]=f[index<<1|1];
 77     }
 78 }
 79 
 80 int query(int index,int l,int r,int x,int y)
 81 {
 82     if (x<=l && r<=y)
 83         return f[index];
 84     if (r<x || l>y)
 85         return 0;
 86     int m=(l+r)>>1;
 87     int p=query(index<<1,l,m,x,y);
 88     int q=query(index<<1|1,m+1,r,x,y);
 89     if (b[p]<b[q])
 90         return p;
 91     else
 92         return q;
 93 }
 94 
 95 int main()
 96 {
 97     int n,q,root,x,y,i,j,m,d;
 98     node *p;
 99     scanf("%d%d%d",&n,&q,&root);
100     for (i=1;i<n;i++)
101     {
102         scanf("%d%d",&x,&y);
103         p=(node*) malloc (sizeof(node));
104         p->d=y;
105         p->next=e[x];
106         e[x]=p;
107 
108         p=(node*) malloc (sizeof(node));
109         p->d=x;
110         p->next=e[y];
111         e[y]=p;
112     }
113     dfs(root,1);
114 
115     b[0]=n+1;
116     build(1,1,s);
117     while (q--)
118     {
119         scanf("%d%d",&x,&y);
120         x=lef[x];
121         y=lef[y];
122         if (x>y)
123             swap(x,y);
124         printf("%d
",a[query(1,1,s,x,y)]);
125     }
126     return 0;
127 }

 

3.离线dfs

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <time.h>
  6 #include <string>
  7 #include <set>
  8 #include <map>
  9 #include <list>
 10 #include <stack>
 11 #include <queue>
 12 #include <vector>
 13 #include <bitset>
 14 #include <ext/rope>
 15 #include <algorithm>
 16 #include <iostream>
 17 using namespace std;
 18 #define ll long long
 19 #define minv 1e-6
 20 #define inf 1e9
 21 #define pi 3.1415926536
 22 #define E  2.7182818284
 23 const ll mod=1e9+7;//998244353
 24 const int maxn=5e5+10;
 25 
 26 struct node
 27 {
 28     int d;
 29     node *next;
 30 }*e[maxn];
 31 struct rec
 32 {
 33     int d,index;
 34     rec *next;
 35 }*ask[maxn];
 36 bool vis[maxn]={0};
 37 
 38 int r[maxn],fa[maxn];
 39 
 40 int getfather(int d)
 41 {
 42     if (fa[d]==d)
 43         return d;
 44     fa[d]=getfather(fa[d]);
 45     return fa[d];
 46 }
 47 
 48 void merge(int x,int y)
 49 {
 50     int s=getfather(x);
 51     int t=getfather(y);
 52     fa[t]=s;
 53 }
 54 
 55 void dfs(int d)
 56 {
 57     node *p;
 58     rec *v;
 59     vis[d]=1;
 60 
 61     p=e[d];
 62     while (p)
 63     {
 64         if (!vis[p->d])
 65         {
 66             dfs(p->d);
 67             merge(d,p->d);
 68         }
 69         p=p->next;
 70     }
 71 
 72     v=ask[d];
 73     while (v)
 74     {
 75         if (vis[v->d])
 76             r[v->index]=getfather(v->d);
 77         v=v->next;
 78     }
 79 }
 80 
 81 int main()
 82 {
 83     node *p;
 84     rec *v;
 85     int n,q,root,x,y,i;
 86     scanf("%d%d%d",&n,&q,&root);
 87     for (i=1;i<n;i++)
 88     {
 89         scanf("%d%d",&x,&y);
 90         p=(node*) malloc (sizeof(node));
 91         p->d=y;
 92         p->next=e[x];
 93         e[x]=p;
 94 
 95         p=(node*) malloc (sizeof(node));
 96         p->d=x;
 97         p->next=e[y];
 98         e[y]=p;
 99     }
100 
101     for (i=1;i<=q;i++)
102     {
103         scanf("%d%d",&x,&y);
104         v=(rec*) malloc (sizeof(rec));
105         v->d=y;
106         v->index=i;
107         v->next=ask[x];
108         ask[x]=v;
109 
110         v=(rec*) malloc (sizeof(rec));
111         v->d=x;
112         v->index=i;
113         v->next=ask[y];
114         ask[y]=v;
115     }
116 
117     for (i=1;i<=n;i++)
118         fa[i]=i;
119     dfs(root);
120     for (i=1;i<=q;i++)
121         printf("%d
",r[i]);
122     return 0;
123 }

 

以上是关于lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs的主要内容,如果未能解决你的问题,请参考以下文章

HDU 2586(LCA欧拉序和st表)

[算法整理]树上求LCA算法合集

CS20 D LCA

LCA--倍增法

dfs序+RMQ求LCA详解

树的经典问题和方法