前几天看到LCA,发现有种O(n)-O(1)的做法。本想找板子学习一下,苦寻无果。那就自己写写板子吧!因为实在才疏学浅,各位大佬要是遇到bug,或是wa的题。请告诉我!我去改!

//duobly On - O1
//顶点1-n
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;const int maxn = 3e5 + 7; // 32768k = 4m 内存只够1e6
const int maxlen = 7e4 + 7; // n / BASE
struct edge {int to, next, dist;
}e[2 * maxn];struct LCA
{int n; // 顶点数int tol; // 边的数量int cnt; // dfs搜索数量int root; //树根int head[maxn]; // i的第一条边int fa[maxn]; // 父节点int efa[maxn]; //指向父节点的边int dis[maxn]; //结点到根的距离int dep[2 * maxn];int ver[2 * maxn];// 欧拉序列 前深度后顶点int ind[maxn]; // 顶点i在数组第一次出现的位置int BASE = 15; //分块长度int STlen; // st表分块后长度int sta[1 << 14][15][15]; // 状态查找int STsta[maxlen]; // 每块的状态int msn[23][maxlen]; // st表int lg[maxlen]; // logi 向下取整void pre()//预处理{lg[1] = 0;for(int i = 2; i < 60007; i ++){lg[i] = lg[i - 1];if(!(i & (i - 1)))lg[i] ++;}for(int i = 0; i < (1 << (BASE - 1)); i ++){for(int l = 0; l < BASE; l ++){sta[i][l][l] = l;int now = 0, minv = 0;for(int r = l + 1; r < BASE; r ++){sta[i][l][r] = sta[i][l][r - 1];if((1 << (r - 1)) & i)now ++;else{now --;if (now < minv){minv = now;sta[i][l][r] = r;}}}}}}void init(int n, int root) //重置{this->n = n;this->root = root;tol = 0;cnt = 0;for(int i = 0; i <= n; i ++){head[i] = fa[i] = ind[i] = -1;}fa[root] = -2;efa[root] = -1;dis[root] = 0;}void addedge (int u, int v, int d) //加边{e[tol].to = v; e[tol].dist = d;e[tol].next = head[u]; head[u] = tol++;e[tol].to = u; e[tol].dist = d;e[tol].next = head[v]; head[v] = tol++;}void dfs(int u, int d){dep[cnt] = d;ver[cnt] = u;if(ind[u] == -1){ind[u] = cnt;}cnt++;if(head[u] == -1)return;for(int i = head[u]; i != -1; i = e[i].next){int temp = e[i].to;if(fa[temp] == -1){fa[temp] = u;efa[temp] = i;dis[temp] = e[i].dist + dis[u];dfs(temp, d + 1);dep[cnt] = d;ver[cnt++] = u;}}}void work() //输入边后处理{dfs(root, 0);STlen = (2 * n - 2) / BASE + 1;for(int i = 0; i < 2 * n - 1; i ++){if(i % BASE == 0) //块首{msn[0][i / BASE] = i; //块内最值地址STsta[i / BASE] = 0; //状态序列}else{if(dep[i] < dep[msn[0][i / BASE]])msn[0][i / BASE] = i; // 更新地址if(dep[i] > dep[i - 1])STsta[i / BASE] |= 1 << (i % BASE - 1); //大于差分序列为1}}for(int j = 1; (1 << j) <= STlen; j ++) // j < lgn{for(int i = 0; i + (1 << j) - 1 < STlen; i ++){int b1 = msn[j - 1][i], b2 = msn[j - 1][i + (1 << (j - 1))];msn[j][i] = dep[b1] < dep[b2]? b1 : b2;}}}int querymin(int L, int R)  //返回位置{int idl = L / BASE, idr = R / BASE;if(idl == idr)return idl * BASE + sta[STsta[idl]][L % BASE][R % BASE];else{int b1 = idl * BASE + sta[STsta[idl]][L % BASE][BASE - 1];int b2 = idr * BASE + sta[STsta[idr]][0][R % BASE];int buf = dep[b1] < dep[b2]? b1 : b2;if(idr - idl - 1){int c = lg[idr - idl - 1];int b1 = msn[c][idl + 1];int b2 = msn[c][idr - (1 << c)];int b = dep[b1] < dep[b2]? b1 : b2;return dep[buf] < dep[b]? buf : b;}return buf;}}int lcadep(int x, int y) //祖先所在深度{int L = ind[x];int R = ind[y];if(L > R)swap(L, R);return dep[querymin(L, R)];}int lcaver(int x, int y) //祖先顶点{int L = ind[x];int R = ind[y];if(L > R)swap(L, R);return ver[querymin(L, R)];}/*void pri(){cout<<STlen<<endl;for(int i = 0; i < 2 * n - 1; i++)printf("%d ", dep[i] );cout<<endl;for(int i = 0; i < 2 * n - 1; i++)printf("%d ", ver[i]);cout<<endl;for(int i = 1; i <= n; i++)printf("%d ", ind[i]);cout<<endl;for(int i = 0; i <= lg[STlen]; i++){for(int j = 1; j <= STlen; j++)if(j + bin[i]  - 1 <= STlen){cout<<msn[i][j]<<"  ";}printf("\n");}}
*/
///*int bin[23];int maxx[23][maxn];int minx[23][maxn];int lgg[maxn];void rangework(){ST_buildmin(n);ST_buildmax(n);}int rangever(int x, int y) //区间lca查询{int L = ST_min(x, y);int R = ST_max(x, y);if(L > R)swap(L, R);return ver[querymin(L, R)];}void ST_buildmin(int n){lgg[0] = -1;for(int i = 1; i <= n; i++)lgg[i] = lgg[i / 2] + 1;bin[0] = 1;for(int j = 1; j < 23; j++)bin[j] = bin[j - 1] * 2;for(int i = 1; i <= n; i++){minx[0][i] = ind[i];}for(int i = 1; i <= lgg[n]; i++)for(int j = 1; j + bin[i] - 1 <= n; j++)minx[i][j] = min(minx[i - 1][j], minx[i - 1][j + bin[i - 1]]);}void ST_buildmax(int n){for(int i = 1; i <= n; i++){maxx[0][i] = ind[i];}for(int i = 1; i <= lgg[n]; i++)for(int j = 1; j + bin[i] - 1 <= n; j++)maxx[i][j] = max(maxx[i - 1][j], maxx[i - 1][j + bin[i - 1]]);}int ST_min(int x, int y){if(x > y)swap(x, y);int temp = lgg[y - x + 1];return min(minx[temp][x], minx[temp][y - bin[temp] + 1]);}int ST_max(int x, int y){if(x > y)swap(x, y);int temp = lgg[y - x + 1];return max(maxx[temp][x], maxx[temp][y - bin[temp] + 1]);}
//*/
}lca;int n, m;
int main()
{lca.pre(); //预处理while(scanf("%d", &n) == 1){int u, v, d;lca.init(n, 1); //重置for(int i = 0; i < n - 1; i++){scanf("%d%d", &u, &v);lca.addedge(u, v, 0); //添加边}lca.work(); //lca处理lca.rangework(); //区域lca处理//lca.lcadep(x, y); //祖先深度//lca.lcaver(x, y); //祖先结点scanf("%d", &m);int x, y;for(int i = 1; i <=  m; i++){scanf("%d%d", &x, &y);printf("%d\n", lca.rangever(x, y));}}}

最近公共祖(LCA)模板_祖先深度_区域祖先_(欧拉序列+标准RMQ+四毛子)O(n)-O(1)相关推荐

  1. Duan2baka的各种LCA模板!

    (这篇文章是模板向-了解具体思想还是看网上其他详细讲解吧QAQ) LCA,即最近公共祖先,是在有根树中两个点最近的公共祖先,在树上问题中非常有用QAQ 常用LCA求法: 一.树链剖分LCA 树链剖分L ...

  2. HDU2586——How far away ?(LCA模板)

    How far away ? 题意:给出一棵树,问两个节点x,y之间的最短距离是多少(边权值). 思路:用根节点到x的距离+根节点到y的距离−多走的距离根节点到x的距离+根节点到y的距离-多走的距离根 ...

  3. hdu 2586 How far away ?(LCA模板)(倍增法)

    在dfs的过程中维护三个数组:  deep[i],表示i点在树中的深度:  grand[x][i],表示x的第2^i个祖先的节点编号:  dis[x][i],表示x到它2^i祖 #include< ...

  4. HDU - 4547 CD操作(LCA模板)

    题目链接:点击查看 题目大意:给出一个层层嵌套的树状结构,可以从某一点通过一个操作直接到达任意一个子节点的位置,但如果要从某个节点到达其祖先节点需要一层一层往上爬,问若要从节点A到达节点B,需要多少步 ...

  5. 深度学习:在图像上找到手势_使用深度学习的人类情绪和手势检测器:第1部分

    深度学习:在图像上找到手势 情感手势检测 (Emotion Gesture Detection) Has anyone ever wondered looking at someone and tri ...

  6. 基于深度搜索的树路径求解_基于深度学习的自动验证码求解器

    基于深度搜索的树路径求解 计算机视觉,网络安全,深度学习(Computer Vision, Cybersecurity, Deep Learning) Disclaimer: The followin ...

  7. c语言微信昵称大全女生优雅经典的,微信昵称大全女生优雅_有深度有内涵的昵称...

    微信昵称大全女生优雅_有深度有内涵的昵称 相关内容: 情侣网名就是两人在网络中相互定位的暧昧称呼,情侣网名受到很多年轻情侣喜爱.以下是第一范文网小编为你整理的20xx最新版情侣专用网名,希望能帮到你. ...

  8. 深度学习实践:计算机视觉_深度学习与传统计算机视觉技术:您应该选择哪个?

    深度学习实践:计算机视觉 计算机视觉 (Computer Vision) Deep Learning(DL) is undeniably one of the most popular tools u ...

  9. 深度学习将灰度图着色_通过深度学习为视频着色

    深度学习将灰度图着色 零本地设置/ DeOldify / Colab笔记本 (Zero Local Setup / DeOldify / Colab Notebook) "Haal Kais ...

  10. 深度学习模型建立过程_所有深度学习都是统计模型的建立

    深度学习模型建立过程 Deep learning is often used to make predictions for data driven analysis. But what are th ...

最新文章

  1. php点击根据价格升降序,织梦列表页点击按价格按评分按更新按点击排序进行筛选方法...
  2. 【数据算法】Java实现二叉树存储以及遍历
  3. 利用JavaScript实现简单的下拉菜单
  4. 【转】每天一个linux命令(61):wget命令
  5. 「一本通 4.1 例 3」校门外的树 (loj10115)
  6. 为什么我们不再购买技术类书籍
  7. CPU-AMD处理器的驱动下载地址
  8. 根据RGB配色改变图片颜色
  9. Python实现历史记录功能
  10. 农业技术:从能量的角度看农业革命(垄耕种植法)
  11. flutter打包安卓问题
  12. 大二Web课程设计 HTML+CSS制作苹果商城网站 Apple商城 8个页面
  13. VS Code全局搜索
  14. Merriam-Webster's Vocabulary Builder 学习笔记 Unit 18
  15. windows10怎么备份操作系统
  16. E - LEQ(树状数组)
  17. 《数据结构实践》设计报告---迷宫求解
  18. 内存对齐的原理,作用,例子以及一些规划(中英文说明,适用sizeof结构体) ...
  19. 抖音中的搞笑BGM如何提取,MP3转换器怎么使用
  20. 07.微软又一逆天可视化神器——Power BI

热门文章

  1. 百度招聘Android客服端(1)
  2. Gephi启动错误:Cannot load even default layout, using internally predefined
  3. java flip_GitHub - bowen903/ViewFlipAnimator: 一种超简单纯Java实现的卡片翻转效果
  4. Java面试题----基础
  5. Google Draco 源码解析
  6. 【Python 实战基础】如何绘制关系网格图展示8个节点间的关系
  7. 微信小程序云开发之简单两步实现集成赞赏加群弹窗功能
  8. Dungeon Game
  9. 二阶魔方高级玩法公式
  10. 以太坊 2.0 中的验证者经济模型,Part-2