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

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

1.欧拉序+rmq(st)

 /*
在这里,对于一个数,选择最左边的
选择任意一个都可以,[left_index,right_index],深度都大于等于这个数的深度
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <time.h>
#include <string>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <ext/rope>
#include <algorithm>
#include <iostream>
using namespace std;
#define ll long long
#define minv 1e-6
#define inf 1e9
#define pi 3.1415926536
#define E 2.7182818284
const ll mod=1e9+;//
const int maxn=5e5+; struct node
{
int d;
node *next;
}*e[maxn]; int s=; ///每条边走两遍,n-1条边,走2(n-1)个点
int a[maxn<<],b[maxn<<],f[maxn<<][],lef[maxn],er[];
bool vis[maxn]={}; void dfs(int d,int dep)
{
node* p=e[d];
vis[d]=;
s++;
lef[d]=s;
a[s]=d;
b[s]=dep;
while (p)
{
if (!vis[p->d])
{
dfs(p->d,dep+);
s++;
a[s]=d;
b[s]=dep;
}
p=p->next;
}
} int main()
{
int n,q,root,x,y,i,j,k,m,d;
node *p;
scanf("%d%d%d",&n,&q,&root);
for (i=;i<n;i++)
{
scanf("%d%d",&x,&y);
p=(node*) malloc (sizeof(node));
p->d=y;
p->next=e[x];
e[x]=p; p=(node*) malloc (sizeof(node));
p->d=x;
p->next=e[y];
e[y]=p;
}
dfs(root,); m=log(s)/log();
er[]=;
for (i=;i<=m;i++)
er[i]=er[i-]<<;
for (i=;i<=s;i++)
f[i][]=i;
// f[i][0]=b[i];
for (i=;i<=m;i++) //2^i
for (j=,k=j+er[i-];j<=s-er[i]+;j++,k++) //-er[i]+1
if (b[ f[j][i-] ] < b[ f[k][i-] ])
f[j][i]=f[j][i-];
else
f[j][i]=f[k][i-];
// f[j][i]=min(f[j][i-1],f[j+er[i-1]][i-1]); while (q--)
{
scanf("%d%d",&x,&y);
x=lef[x];
y=lef[y];
if (x>y)
swap(x,y);
d=log(y-x+)/log();
j=y-er[d]+;
if (b[ f[x][d] ] < b[ f[j][d] ]) //+1
printf("%d\n",a[ f[x][d] ]);
else
printf("%d\n",a[ f[j][d] ]);
// printf("%d\n",min(f[x][d],f[y-er[d]+1][d]));
}
return ;
}
/*
8 100 1
1 2
1 3
2 4
2 5
3 6
5 7
6 8 5 7
5
2 3
1
3 2
1
1 8
1
2 8
1
4 5
2
5 4
2
*/

2.欧拉序+线段树

 /*
在这里,对于一个数,选择最左边的
选择任意一个都可以,[left_index,right_index],深度都大于等于这个数的深度
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <time.h>
#include <string>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <ext/rope>
#include <algorithm>
#include <iostream>
using namespace std;
#define ll long long
#define minv 1e-6
#define inf 1e9
#define pi 3.1415926536
#define E 2.7182818284
const ll mod=1e9+;//
const int maxn=5e5+; struct node
{
int d;
node *next;
}*e[maxn]; int s=; ///每条边走两遍,n-1条边,走2(n-1)个点
int a[maxn<<],b[maxn<<],lef[maxn],f[maxn<<];
bool vis[maxn]={};
int num=; void dfs(int d,int dep)
{
node* p=e[d];
vis[d]=;
s++;
lef[d]=s;
a[s]=d;
b[s]=dep;
while (p)
{
if (!vis[p->d])
{
dfs(p->d,dep+);
s++;
a[s]=d;
b[s]=dep;
}
p=p->next;
}
} void build(int index,int l,int r)
{
if (l==r)
f[index]=++num;
else
{
int m=(l+r)>>;
build(index<<,l,m);
build(index<<|,m+,r);
if (b[f[index<<]]<b[f[index<<|]])
f[index]=f[index<<];
else
f[index]=f[index<<|];
}
} int query(int index,int l,int r,int x,int y)
{
if (x<=l && r<=y)
return f[index];
if (r<x || l>y)
return ;
int m=(l+r)>>;
int p=query(index<<,l,m,x,y);
int q=query(index<<|,m+,r,x,y);
if (b[p]<b[q])
return p;
else
return q;
} int main()
{
int n,q,root,x,y,i,j,m,d;
node *p;
scanf("%d%d%d",&n,&q,&root);
for (i=;i<n;i++)
{
scanf("%d%d",&x,&y);
p=(node*) malloc (sizeof(node));
p->d=y;
p->next=e[x];
e[x]=p; p=(node*) malloc (sizeof(node));
p->d=x;
p->next=e[y];
e[y]=p;
}
dfs(root,); b[]=n+;
build(,,s);
while (q--)
{
scanf("%d%d",&x,&y);
x=lef[x];
y=lef[y];
if (x>y)
swap(x,y);
printf("%d\n",a[query(,,s,x,y)]);
}
return ;
}

3.离线dfs

 #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <time.h>
#include <string>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <ext/rope>
#include <algorithm>
#include <iostream>
using namespace std;
#define ll long long
#define minv 1e-6
#define inf 1e9
#define pi 3.1415926536
#define E 2.7182818284
const ll mod=1e9+;//
const int maxn=5e5+; struct node
{
int d;
node *next;
}*e[maxn];
struct rec
{
int d,index;
rec *next;
}*ask[maxn];
bool vis[maxn]={}; int r[maxn],fa[maxn]; int getfather(int d)
{
if (fa[d]==d)
return d;
fa[d]=getfather(fa[d]);
return fa[d];
} void merge(int x,int y)
{
int s=getfather(x);
int t=getfather(y);
fa[t]=s;
} void dfs(int d)
{
node *p;
rec *v;
vis[d]=; p=e[d];
while (p)
{
if (!vis[p->d])
{
dfs(p->d);
merge(d,p->d);
}
p=p->next;
} v=ask[d];
while (v)
{
if (vis[v->d])
r[v->index]=getfather(v->d);
v=v->next;
}
} int main()
{
node *p;
rec *v;
int n,q,root,x,y,i;
scanf("%d%d%d",&n,&q,&root);
for (i=;i<n;i++)
{
scanf("%d%d",&x,&y);
p=(node*) malloc (sizeof(node));
p->d=y;
p->next=e[x];
e[x]=p; p=(node*) malloc (sizeof(node));
p->d=x;
p->next=e[y];
e[y]=p;
} for (i=;i<=q;i++)
{
scanf("%d%d",&x,&y);
v=(rec*) malloc (sizeof(rec));
v->d=y;
v->index=i;
v->next=ask[x];
ask[x]=v; v=(rec*) malloc (sizeof(rec));
v->d=x;
v->index=i;
v->next=ask[y];
ask[y]=v;
} for (i=;i<=n;i++)
fa[i]=i;
dfs(root);
for (i=;i<=q;i++)
printf("%d\n",r[i]);
return ;
}

4.倍增

 #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <time.h>
#include <string>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <ext/rope>
#include <algorithm>
#include <iostream>
using namespace std;
#define ll long long
#define minv 1e-6
#define inf 1e9
#define pi 3.1415926536
#define nl 2.7182818284
const ll mod=1e9+;//
const int maxn=5e5+; struct node
{
int d;
node *next;
}*e[maxn]; bool vis[maxn]={};
int q[maxn],dep[maxn],f[maxn][]; int main()
{
node *p;
int n,Q,root,head,tail,x,y,d,dd,i,j,k;
scanf("%d%d%d",&n,&Q,&root);
for (i=;i<n;i++)
{
scanf("%d%d",&x,&y);
p=new node();
p->d=y;
p->next=e[x];
e[x]=p; p=new node();
p->d=x;
p->next=e[y];
e[y]=p;
} head=,tail=;
vis[root]=;
q[]=root;
dep[root]=;
while (head<tail)
{
head++;
d=q[head];
p=e[d];
while (p)
{
dd=p->d;
if (!vis[dd])
{
tail++;
q[tail]=dd;
vis[dd]=;
dep[dd]=dep[d]+;
//f[dd][]=d; j=d;
k=;
while (j)
{
f[dd][k]=j;
j=f[j][k];
k++;
}
}
p=p->next;
}
}
while (Q--)
{
scanf("%d%d",&x,&y);
if (dep[x]<dep[y])
swap(x,y); i=dep[x]-dep[y];
j=;
while (i)
{
if (i & )
x=f[x][j];
i>>=;
j++;
} if (dep[x]==)
k=;
else
k=log(dep[x]+minv)/log()+;
i=(<<k);
while (k)
{
k--;
i>>=;
if (dep[x]>=i && f[x][k]!=f[y][k])
{
x=f[x][k];
y=f[y][k];
}
}
if (x!=y)
x=f[x][];
printf("%d\n",x);
}
return ;
}
/*
5 100 1
1 2
2 3
3 4
4 5 1 5
3 4
2 4
2 5 7 100 1
1 2
2 3
2 4
4 5
4 6
1 7 5 7
3 7
5 1
2 6
3 6 10 100 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10 1 10
2 10
3 10
4 10
5 9
7 8 10 100 1
1 2
2 3
3 4
3 5
5 6
5 7
2 8
8 9
9 10 6 10
4 10
3 1
6 7
3 10
2 10
3 7
6 7
4 7 10 100 1
1 2
1 3
1 4
3 5
3 6
3 7
7 8
7 9
7 10 15 100 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
12 13
13 14
14 15 1 15
2 15
2 14
3 14
3 13
4 13
4 12 12 100 1
1 2
2 3
3 4
4 5
5 6
1 7
7 8
8 9
9 10
10 11
11 12 6 12
4 7
8 12
1 6
*/
上一篇:Word 宏命令大全


下一篇:并行程序设计模式--Master-Worker模式