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. 20155317 王新玮《网络对抗技术》实验5 MSF基础应用

    20155317 王新玮<网络对抗技术>实验5 MSF基础应用 1. MS08_067安全漏洞 原理:攻击者利用受害者主机默认开放的SMB服务端口445,发送特殊RPC请求,通过MSRPC ...

  2. 20155320《网络对抗》Exp4 恶意代码分析

    20155320<网络对抗>Exp4 恶意代码分析 [系统运行监控] 使用schtasks指令监控系统运行 首先在C盘目录下建立一个netstatlog.bat文件(由于是系统盘,所以从别 ...

  3. EZ 2018 05 04 NOIP2018 模拟赛(十二)

    这次的试卷应该是激励我们一下的,链接 然后大家的分数就都很高,然后我就210被一群秒A T2的240大佬爆踩 掉了5rating但Rank竟然发杀了 X_o_r dalao && YZ ...

  4. libgdx学习记录19——图片动态打包PixmapPacker

    libgdx中,opengl 1.x要求图片长宽必须为2的整次幂,一般有如下解决方法 1. 将opengl 1.x改为opengl 2.0.(libgdx 1.0版本后不支持1.x,当然不存在这个问题 ...

  5. SpringMVC RestTemplate的几种请求调用

    转载:https://blog.csdn.net/ThinkingLink/article/details/45366777 1.用统一的方法模板进行四种请求:POST,PUT,DELETE,GET ...

  6. c++时间计算模块

    c++时间计算模块 可用于计算代码运行耗时.计算代码运行时间线(比如处理与运行时间相关函数). 该模块从实际项目中产生,使用方式仁者见仁智者见智,设计思想可供参考. 源码: //author: cai ...

  7. H5游戏接微信小游戏的支付,满满的都是坑!

    h5小游戏接微信的支付,简直是在为难我胖虎,说多了都是泪. 准备工作: 准备工作一定要做好,不然很容易出错.首先是session_key这个字段,这个session_key是登录的时候需要用到的,根据 ...

  8. 扩展webservice

    描述: 最近一个winform项目刚开发完成.采用c/s架构.闲来把一些技术点整理下了. 做项目之前调研了客户的电脑 .客户端机子性能一般,而且都是基于xp. 这些客观存在的问题,注定了实现过程中必须 ...

  9. PAT-1045. Favorite Color Stripe (30)-LIS

    将Eva喜欢的颜色按顺序编个优先级, 2 3 1 5 6-> 1 2 3 4 5 然后读取stripe,将Eva不喜欢的先剔除掉,剩下的颜色替换为相应的优先级 2 2 4(去掉) 1 5 5 6 ...

  10. Python中的字典详解

    https://www.cnblogs.com/yjd_hycf_space/p/6880026.html