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. EZ 2018 03 23 NOIP2018 模拟赛(五)

    链接:http://211.140.156.254:2333/contest/65 这次Rating重回Rank18,我是20的守门员(滑稽) 这次题目和数据普遍偏水,我T2打错了一个变量名竟然过了所 ...

  2. 原创zynq文章整理(MiZ702教程+例程)

    MiZ702教程+例程  网盘链接:  http://pan.baidu.com/s/1sj23yxv 不时会跟新版本,增加勘误之类的,请关注--

  3. 蒙特卡罗方法 python 实现

    蒙特卡罗(Monte Carlo)方法的精髓:用统计结果去计算频率,从而得到真实值的近似值. 一.求圆周率的近似值,采用 投点法 import numpy as np import matplotli ...

  4. TMS320VC5509片内ADC采集

    1. ADC采集比较简单,内部的10位的ADC,AIN0-AIN3的输入,主要是用的CSL的库函数#include <csl_adc.h> ; Uint16 samplestoraage[ ...

  5. 10、Dockerfile实战-PHP

    一.镜像制作步骤 安装编译依赖包 编译安装 配置 二.编写Dockerfile FROM centos:7 MAINTAINER QUNXUE RUN yum install -y gcc gcc-c ...

  6. shellcode 初次使用笔记

    winXP SP3 环境 (xp环境默认没开启栈不可执行机制,比较方便破解,如果已开启了,请自行百度如何关闭) dig.exe 目标文件 x86dbg调试工具 python 环境 打开准备好的目标软件 ...

  7. OD之去除nag弹窗(四)

    在某些方面,一个软件如果没有注册的话,老是会弹出烦人的注册弹窗,就如下图一样: 出现了两次弹窗,开始一次,关闭后又一次,老办法,拖进OD进行分析;不过看出程序很简单,就出现了messagebox的调用 ...

  8. VMware下三种网络连接模式介绍

    birdged(桥接) 桥接网络是指本地物理网卡和虚拟网卡通过VMnet0虚拟交换机进行桥接,物理网卡和虚拟网卡在拓扑图上处于同等地位,那么物理网卡和虚拟网卡就相当于处于同一个网段,虚拟交换机就相当于 ...

  9. ERP条码解决方案,金蝶盘点机条码解决方案,应用PDA的信息化管理能给我们的生产管理带来怎么样的变化的探讨

    ERP条码解决方案,金蝶盘点机条码解决方案,应用PDA的信息化管理能给我们的生产管理带来怎么样的变化的探讨. 当前越来越多的大大小小的中国企业已经接受了ERP的思想,大多数的商店,企业,工厂都会上一套 ...

  10. 《Macro-Micro Adversarial Network for Human Parsing》论文阅读笔记

    <Macro-Micro Adversarial Network for Human Parsing> 摘要:在人体语义分割中,像素级别的分类损失在其低级局部不一致性和高级语义不一致性方面 ...