说在博客前

这篇博客有许多使用到 STL 的地方,由于本人实在是记不全,所以我也参考了北大的一些教材,就别说我黈力了 QwQ

数据结构

今天讲的是数据结构啦(也是我这个蒟蒻最喜欢的

一些天天见面的好盆友

栈,队列

这些吧都是些挺水的东西,我就口胡口胡。(结果口胡着口胡着过万了??????)

值得一提的是 队列常用于 bfs,栈一般就是用于中序和后序遍历

堆是一种很有意思的数据结构

它允许元素的堆顶弹出,堆低插入,而 c++ 当中的 stl 提供了 priority_queue(优先队列)这个容器,允许你对于这个队列采用特定的方式优先排序

对于一个堆,我们一般只说大根堆和小根堆,c++ 默认是大根堆,想要实现小根堆,我们可以这样

  1. priority_queue<int, vector<int>, greater<int> >;//注意此处 > 要用空格空开,有可能识别为右移

倍增求 LCA

我们有一棵树,定义一棵树上的点到根结点的路径上所有的点都是它的祖先,LCA 指的就是两个数的最近公共祖先

步骤大体是这样

1. 如果 A 的深度小于 B 的深度,就把他们互换

2. 把 a 向上调到和 b 一样的高度,直到 ab 一样高(此时 ab 可以进行互换)

3. 把 a 和 b 一起上调,直到 ab 相同

这种算法复杂度是 O(deep) 的,但是当树是一条类似于链的结构,就废了,考虑为什么?

我们是一层一层跳的,自然会很慢,所以我们可以考虑倍增着来求 LCA



p [x] [i]

表示 x 向后 2^i 的祖先是谁,显然 p[x] [i] = p[ p [x] [i - 1] ] [i - 1]

用这张图举例,我们想要求出 4,5 的 LCA

就要

1. 先 dfs 所有点,处理出每一个点的深度

2. 然后把深度更深的那一个点(4)一个点地一个点地往上跳,直到到某个点(3)和另外那个点(5)的深度一样

然后两个点一起一个点地一个点地往上跳,直到到某个点(就是最近公共祖先)两个点“变”成了一个点

不过有没有发现一个点地一个点地跳很浪费时间?

如果一下子跳到目标点内存又可能不支持,相对来说倍增的性价比算是很高的

  倍增的话就是一次跳 2^i 个点,不难发现深度差为 x 时,深度更深的那个点就需要跳 x 个点

所以代码就是这个样子

  1. if (depth[a] < depth[b])
  2. swap(a, b);
  3. int c = depth[a] - depth[b];
  4. for (int i = 0; i <= 20; i++)
  5. {
  6. if (c & (1 << i))
  7. {
  8. a = up[a][i];
  9. }
  10. }

这样子看起来很不错对吧,但是会出现一个问题,那就是跳到的公共祖先不一定是最近的

所以倍增找 LCA 的方法是这样的

在两个人平了之后,从最大可以跳的步数开始跳(一定是 2^i),

(这就是为什么我们说求 LCA 的过程很像二进制分解的原因了)

如果跳的到的位置一样,就不跳,如果不一样才跳,每次跳的路程是前一次的一半

这样做有一个缺点,就是它找到的点是最靠近 LCA 的点,也就是再跳一步就是 LCA,不过问题不大

在上代码之前,说几句

我个人是比较喜欢预处理和dfs写在一起的,然后fa[i] 我也直接用fji代替了,所以省了一点点空间吧

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5. using namespace std;
  6. const int Maxn = 500005, Maxc = 20;
  7. int n, x, y, s, m;
  8. int head[Maxn], edge_num = 0;
  9. struct EDGE
  10. {
  11. int next, to;
  12. } e[Maxn * 2];
  13. int dep[Maxn];
  14. bool visited[Maxn];
  15. int fa[Maxn][21];
  16. inline void add(int from, int to)
  17. {
  18. e[++edge_num].next = head[from];
  19. e[edge_num].to = to;
  20. head[from] = edge_num;
  21. }
  22. void dfs(int u, int father)
  23. {
  24. dep[u] = dep[father] + 1;
  25. fa[u][0] = father;
  26. for (int i = 0; i <= Maxc - 1; ++i)
  27. fa[u][i + 1] = fa[fa[u][i]][i];
  28. for (int i = head[u]; i; i = e[i].next)
  29. {
  30. int v = e[i].to;
  31. if (v != father)
  32. dfs(v, u);
  33. }
  34. }
  35. inline int LCA(int x, int y)
  36. {
  37. if (dep[x] < dep[y])
  38. swap(x, y); //让A在下面
  39. for (int i = Maxc; i >= 0; --i)
  40. {
  41. if (dep[fa[x][i]] >= dep[y])
  42. x = fa[x][i];
  43. if (x == y)
  44. return x;
  45. }
  46. for (int i = Maxc; i >= 0; --i)
  47. if (fa[x][i] != fa[y][i])
  48. x = fa[x][i], y = fa[y][i];
  49. return fa[x][0];
  50. }
  51. int main()
  52. {
  53. scanf("%d%d%d", &n, &m, &s);
  54. for (int i = 1; i <= n - 1; ++i)
  55. {
  56. scanf("%d%d", &x, &y);
  57. add(x, y);
  58. add(y, x);
  59. }
  60. dfs(s, 0);
  61. while (m--)
  62. {
  63. scanf("%d%d", &x, &y);
  64. printf("%d\n", LCA(x, y));
  65. }
  66. }

不想写了md

D3(没写完的更多相关文章

  1. Word 双栏排版最后多一页空白页删不掉、左栏文字没写完就到右栏了

    1. 问题 问题:Word双栏排版,最后多一页空白页,删不掉.如图: 原因分析:删不掉是因为末尾文字处其实有个下一页分节符,只不过可能看不到. 如何清晰的看到? 视图 > 大纲,就可以看到了.如 ...

  2. XObject.java 对象还没写完,希望电脑不会丢失。坏笑,早点见。

    /*面向对象强调的是对象, 面向过程强调的是功能行为,打开行为,关闭行为,执行行为,把多个行为封装成对象执行更强大的功能就是面向对象,是把多个函数, 多 个行为封装在一起,单一的函数执行对象的功能太困 ...

  3. 【Luogu】【关卡2-7】深度优先搜索(2017年10月)【AK】【题解没写完】

    任务说明:搜索可以穷举各种情况.很多题目都可以用搜索完成.就算不能,搜索也是骗分神器. P1219 八皇后 直接dfs.对角线怎么判断:同一条对角线的横纵坐标的和或者差相同. #include < ...

  4. QBXT Day2主要是数据结构(没写完先占坑)

    简单数据结构 本节课可能用到的一些复杂度: O(log n). 1/1+1/1/.....1/N+O(n log n) 在我们初学OI的时候,总会遇到这么一道题. 给出N次操作,每次加入一个数,或者询 ...

  5. python Web抓取(一)[没写完]

    需要的模块: python web抓取通过: webbrowser:是python自带的,打开浏览器获取指定页面 requests:从因特网上下载文件和网页 Beautiful Soup:解析HTML ...

  6. 前端性能测试工具 : dynaTrace Ajax (还没写完)

    今天开始写这个工具, #什么是dynaTrace Ajax? 随着 jQuery.Dojo.YUI 等框架的兴起让构建 Web2.0 应用更加容易,但随之带来的定位等应用问题也越来越难,尤其是与性能相 ...

  7. D5(太长了md没写完)

    动态规划 三种常见实现方法 对于一个斐波那契数列,我们想要求第n项的值,就需要一项一项的递归来求 来看代码 f[o] = 0; f[1] = 1; for (int i = 2; i <= n; ...

  8. mock的使用及取消,node模仿本地请求:为了解决前后端分离,用户后台没写完接口的情况下

    借鉴:https://www.jianshu.com/p/dd23a6547114 1.说到这里还有一种是配置node模拟本地请求 (1)node模拟本地请求: 补充一下 [1]首先在根目录下建一个d ...

  9. Codeforces Round 212 Div 2 报告(以前没写完,现在也没心情补了,先就这样吧)

    A. Two Semiknights Meet 题目大意:有一个8x8的棋盘,上面放有两个骑士,骑士以“田字”的方式走.每个方格都被定义为good或者bad,问骑士能否在good的格子中相遇? 由于骑 ...

随机推荐

  1. js 重要函数

    1. Array.some some() 方法用于检测数组中的元素是否满足指定条件(函数提供) 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测.如果没有满足条件的元素,则返 ...

  2. Spingboot使用log4j2

    1.pom.xml加入log4j2,并同时把spring boot默认的logging去掉,注意一定要全部排除否则会报错. <dependency> <groupId>org. ...

  3. 目标 - 在虚拟机CentOS7中无图形界面安装Oracle11G R2版本

    参考: https://www.cnblogs.com/yejingcn/p/10278473.html centos7启动oracle su - oracle //切换到自己的oracle账户 ls ...

  4. 抗D十招:十个方法完美解决DDoS攻击防御难题

    可以说,DDoS是目前最凶猛.最难防御的网络攻击之一.现实情况是,这个世界级难题还没有完美的.彻底的解决办法,但采取适当的措施以降低攻击带来的影响.减少损失是十分必要的.将DDoS防御作为整体安全策略 ...

  5. Nginx实用整理

    1. nginx 简述 1.1Nginx是轻量级高并发HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器:Nginx可以作为一个HTTP服务器进行网站的发布处理,另外N ...

  6. centos8 网卡命令(centos7也可用)

    nmcli n 查看nmcli状态 nmcli n on 启动nmcli nmcli c  up eth0 启动网卡eth0 nmcli c down eth0 关闭网卡eth0 nmcli d c ...

  7. PAT Basic 1011 A+B 和 C (15 分)

    给定区间 [−] 内的 3 个整数 A.B 和 C,请判断 A+B 是否大于 C. 输入格式: 输入第 1 行给出正整数 T (≤),是测试用例的个数.随后给出 T 组测试用例,每组占一行,顺序给出  ...

  8. 2019 年百度之星·程序设计大赛 - 初赛一Game HDU 6669 (实现,贪心)

    Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  9. Tree HDU - 6547 (树链剖分,线段树)

    wls 有三棵树,树上每个节点都有一个值 ai,现在有 2 种操作: 将一条链上的所有节点的值开根号向下取整: 求一条链上值的和: 链的定义是两点之间的最短路. Input 第一行两个数 n, q 分 ...

  10. Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)

    题意:有一个长度为n的序列,让你把它分成k段,段内元素取or,段间取and,求能够得到的最大值. 这个算法是我和xz场上yy出来的,然而时间不够了没写出来,而且时间复杂度是$O(nlogn+nlogA ...