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
*/

lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增的更多相关文章

  1. CF877E Danil and a Part-time Job 线段树维护dfs序

    \(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 ...

  2. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

  3. Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

    思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 els ...

  4. BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)

    题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...

  5. 线段树(dfs序建树加区间更新和单点查询)

    题目链接:https://cn.vjudge.net/contest/66989#problem/J 记录一下这道折磨了我一天的题,.... 具体思路: 具体关系可通过dfs序建树,但是注意,在更新以 ...

  6. CF620E New Year Tree 状压+线段树(+dfs序?)

    借用学长的活:60种颜色是突破口(我咋不知道QAQ) 好像这几道都是线段树+dfs序??于是你可以把60种颜色压进一个long long 里,然后向上合并的时候与一下(太妙了~) 所以记得开long ...

  7. 线段树:CDOJ1591-An easy problem A (RMQ算法和最简单的线段树模板)

    An easy problem A Time Limit: 1000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  8. codeforces 877 E. Danil and a Part-time Job(线段树(dfs序))

    题目链接:http://codeforces.com/contest/877/problem/E 题解:显然一看就感觉要么树链剖分要么线段树+dfs序,题目要求的操作显然用线段树+dfs序就可以实现. ...

  9. 最大子序和:暴力->递归->动规->线段树

    题目描述 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. LeetCode:53. 最大子序和 题解 显而易见的暴力解法 最容易想到的便是暴力穷 ...

随机推荐

  1. 【第三方插件】使用Topshelf创建Windows服务

    概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...

  2. apache目录别名

    #默认家目录DocumentRoot "/var/www/html"<Directory "/var/www"> AllowOverride Non ...

  3. stl源码剖析 详细学习笔记 算法(5)

    //---------------------------15/04/01---------------------------- //inplace_merge(要求有序) template< ...

  4. Beta阶段事后分析

    1. 设想和目标 1.1 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们在Beta阶段任务主要分为两部分,一类是对原功能的扩展,一类是新的博文功能.我们通过规 ...

  5. c#版flappybird 未完全实现

    这些天开始在深圳找工作,想着把从前有些淡忘的技术再温故下.看到尊敬的<传智播客>有一期公开课,讲的是用c#编写flappybird小游戏,也就自己搜了下游戏资源,也来试试看. 其实用到的技 ...

  6. 团队作业Week6:规格说明书编写

    (1)请分析你们团队项目的典型用户和场景,并写一个团队博客发布你们团队项目的功能规格说明书. (2)再写一个博客团队博客发布你们项目的设计文档(技术规格说明书). 截止时间:2015-11-03

  7. Android的发展历程及搭建

    Android的发展历程: 对于Android我比较不熟悉,因为我的第一只手机就是iphone,我没用过Android系统,但在中国使用带有Android系统的手机的人数是最多的,所以我想学习Andr ...

  8. Hamburger

    Bread: 我觉得舒婷解决问题的思路还是很不错的,对于java 的窗口框架也是很熟悉,打码速度也快了很多. Meat:但是我发现你在命名的时候会出现随意的现象,如果命名只有你自己看得懂的话,那么会增 ...

  9. Serial,Parallel,CMS,G1四大GC收集器特点小结

    1.Serial收集器一个单线程的收集器,在进行垃圾收集时候,必须暂停其他所有的工作线程直到它收集结束.特点:CPU利用率最高,停顿时间即用户等待时间比较长.适用场景:小型应用通过JVM参数-XX:+ ...

  10. Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作

    一.关于 Python Python 是全球使用人数增长最快的编程语言!它易于入门.功能强大,从 Web 后端 到 数据分析.人工智能,到处都能看到 Python 的身影. Python 有两个主要的 ...