夏令营讲课内容整理Day 1.

主要内容是栈和队列。

1.  栈

运算受到限制的线性表。只允许从一端进行插入和删除等操作。这一端便是栈顶,另一端便是栈底。

其实可以把栈想象层任何有底无盖的柱状的容器。。。毕竟栈满足后进先出的特性。计算机当中调用函数时,中间结果便会保存到「系统栈」中。递归过程也需要栈的协助 。

实现:STL or 手写(请参照一本通 or 课件)

一般操作:判断栈空/满、入栈、出栈,判断栈的大小(请参照一本通 or 课件)

1.1 单调栈

顾名思义,保证内部元素单调(单增或单减)的栈。我们只要在插入新元素的时候,将栈顶所有在插入新元素后不满足单调的元素依次弹出,再插入新元素即可。

对于单调性可以这么理解:所有加入单调队列/单调栈的元素有一个「价值」和「时效性」。价值即为元素的值,时效性则为元素加入的时间。元素加入的时间越久远就越有可能失效。我们要查询在当前还没有失效的所有元素里面谁的价值最高。自然,如果一个元素加入的时间早(更有可能失效),其价值还赶不上后加入的元素,它便没有存在的必要。

本质:内部的元素从栈底到栈顶,价值越来越小,但是时效性越来越强。

应用:DP的优化。

例题:

T1.铁轨

(我在洛谷上找不到这题)

某城市有一个火车站,有n节车厢从A方向驶入车站,按进站顺序编号1~n。火车站只有一个入口,最外面的列车可以驶向B方向。你的任务是判断,一个输入的出站顺序,是否可能是合法的。(所谓合法指存在一种操作车厢的方法,可以得到该出栈顺序。如5 4 1 2 3是不合法的,5 4 3 2 1是合法的)

可以把火车站抽象为一个「栈」。由出栈序列倒推并和入栈序列比较。下一个出栈的车厢序号要么比已出栈的任何一节车厢的序号都大,要么比刚出栈的车厢序号小,才能满足题意。所以我们模拟这个过程,初始火车站是空栈,每次入栈,都与出栈序列进行比对,若相同则将栈顶弹出,不相同则再进一辆。用两个指针i,j分别表示当前第i节车厢已经进站,当前出站序列里面的第j节车厢已经出站。每次如果发现出站序列里面下一个要出站的车厢为当前栈顶的车厢,则让其出站,更新指针j。如果不是,则继续令后面的车厢进站,更新指针i。如果所有车厢已经进站了,但出栈序列没有完成(有车厢滞留了),则所给的出栈序列不是合法的。反之则合法。

T2.等价表达式

luoguP1054。

关于a的表达式变化无常,我们无法对其进行合并同类项。可以考虑特殊值法,但最好不要使用0,1,-1这样的数,这会导致冲突。可以代一些质数去判断两个表达式是否相等。而且要多代几个,也是为了降低冲突产生的概率。(数值法解决问题)

考虑到数据量极大,可能会爆long long。然而这道题使用高精度显然是不现实的,那么怎么办呢?我们考虑计算的时候去模一个你喜欢的质数 ,这样就好很多了。

具体实现方法:双栈。一个是数字栈,一个是符号栈。读入过程比较麻烦,建议寻找网上 题解参考。每当读入数字时压入数字栈,读入符号时要判断。如果是运算符,当前栈顶的运算符优先级大于等于新运算符,则将栈顶运算符弹出,并将当前数字栈顶的两个数进行相应运算,弹出旧数,压入新结果。不停循环,直到栈里面没有符号或符号优先级低于当前新运算符。如果是(,直接压入栈。如果是),则依次将栈里面的符号弹出,并计算。直到遇到一个(。

其实计算方法可以参照一道中缀表达式求值的问题,可以去网上搜一下。

小技巧:可以在表达式开头和结尾分别加一个括号,避免边界的特殊处理。

T3.全排列

全排列大部分情况下都是人工dfs或者algorithm头文件下的next_permutation来实现的。用栈也可以实现,但是几乎没多少人用。基于实用主义的角度,这里不再叙述。

2. 队列

队列也是一种运算受限的线性表。特殊之处在于它的查询和删除操作在队头,而插入操作在队尾(就像日常打饭排队那样)。

队列满足先进先出的特性。(明明是我先来的我应该先出去

队列广泛应用于各种BFS。

实现:实现:STL or 手写(请参照一本通 or 课件)

一般操作:判断队列空/满、入队、出队,判断队列的大小(请参照一本通 or 课件)

2.1 循环队列

一般手写队列存在空间浪费现象,对队首元素进行弹出操作之后,这块内存将无法再次被利用。在一些对于内存要求比较紧张的题目中,可以考虑使用循环队列。

(STL的一般队列就是循环队列,速度的话肯定要比手写慢一点,但是方便啊是不是)

(其实实际上没多少人用

当我们的队首或者队尾指针变成队列大小的最大值的时候,将其对这个最大值取模变为0。这样就实现了让队列首尾相接,不断循环。(具体代码可以去看数据结构基础班的课件)

2.2 双端队列(deque)

顾名思义,这样的队列支持在两端进行插入和删除操作。仅需在手写一般队列的代码上稍加改进即可。但是,千万不要用STL里的deque,那玩意慢的要死。所以如果你真的遇到一道题非得要双端队列做不可,那就老老实实的手写吧。。。

2.3 单调队列

定义类似单调栈。

例题:

T1.课程学习(?)拓扑序列

(我在luogu上找不到这题)

给定一张有向无环图(DAG),来描述某大学之间课程的联系。如果A到B有一条边,说明在学习课程B之前,必须要学习课程A。请找到一条合法的学习课程的序列,满足题目要求。所谓一张有向无环图(DAG)的拓扑序列,即为一个点的序列,满足对任意一条边(u,v),u都出现在v的前面。其实说白点,这个拓扑序列就是说按照一个从小到大的顺序把边排下序,保证前边的点一定要在后边的点的前面 。。。呃这样说可能比较抽象,如果感到理解困难就去看看课件吧。。

拓扑排序是一种类似BFS的方法。对于这个题来说,既然我们前边的点一定要在后边的点的前面,那么我们要找的第一个节点应该是入度为0的点,我们就枚举每个点,如果入度为0就放入队列中。顺序是无所谓的,拓扑排序大多情况下结果是不唯一的。然后我们取出队首节点进行扩展,将所有连接到的点入度-1.为什么不直接放入队列呢?因为可能有一些点有很多其他点相连,也就是有些课程需要的先修课不止一节。遍历完后把所有入度被更新为0的节点放入队列。继续过程直到队列空。在取出队首节点时输出这个节点,那么算法执行完毕后输出的结果就是拓扑排序的结果。

时间: 2024-10-06 04:20:19

夏令营讲课内容整理Day 1.的相关文章

夏令营讲课内容整理Day 0.

今年没有发纸质讲义是最气的.还好我留了点课件. 第一次用这个估计也不怎么会用,但尝试一下新事物总是好的. 前四天gty哥哥讲的内容和去年差不多,后三天zhn大佬讲的内容有点难,努力去理解吧. 毕竟知识还是需要消化的. 这里我只整理知识点,每天上午评测的题目我会单独处理. 嗯大概就是这样了. 写完后我就会考虑发到博客园里.

夏令营讲课内容整理 Day 3.

本日主要内容是树与图. 1.树 树的性质 树的遍历 树的LCA 树上前缀和 树的基本性质: 对于一棵有n个节点的树,必定有n-1条边.任意两个点之间的路径是唯一确定的. 回到题目上,如果题目读入的是树上所有的边,则我们应该想到: 每个点的父亲是谁 每个点的深度 每个点距离根节点的距离 其他的附加信息(例如:子树和,子树最大值..) 遍历整个树的代码如下: 1 void dfs(int now) 2 { 3 deep[now]=deep[fa[now]]+1; 4 sum[now]=value[n

夏令营讲课内容整理 Day 5.

DP专场.. 动态规划是运筹学的一个分支, 求解决策过程最优化的数学方法. 我们一般把动态规划简称为DP(Dynamic Programming) 1.动态规划的背包问题 有一个容量为m的背包,有n个物品,每一个物品i的重量为w[i],价值为v[i]. 要求选择一些物品放入背包中,每种物品只能最多使用一次,使得在不超重的情况下让背包中所有物品价值总和最大. 正常向解法:设状态数组f[i][j]为把前i个物品放入一个容量为j的背包中所能获得的最大价值(以下同设),则状态转移方程为: f[i][j]

夏令营讲课内容整理 Day 4.

本日主要内容就是搜索(打暴力 搜索可以说是OIer必会的算法,同时也是OI系列赛事常考的算法之一. 有很多的题目都可以通过暴力搜索拿到部分分,而在暴力搜索的基础上再加一些剪枝优化, 就有可能会拿到更多的分数. 有句话说的好嘛,骗分过样例,暴力出奇迹. 真的可以出奇迹的,只要你用得好. 1.搜索的概念 在一个给定的空间内,运用一定的查找(遍历)方式,直到找到目标解(状态)的过程,我们称之为搜索. 搜素是尝试性的,搜索是无脑的,搜索是朴素的,搜索在很多时候是显然的,搜索应该总是暴力的.但搜索也是很常

夏令营讲课内容整理 Day 6 Part 1.

Day6讲了三个大部分的内容. 1.STL 2.初等数论 3.倍增 Part1主要与STL有关. 1.概述 STL的英文全名叫Standard Template Library,翻译成中文就叫标准模板库. 它有点类似于一个大型的工具箱,里面包含许多实用工具,可以拿过来直接用而大部分情况下无需去深入探究其内部原理. 不知道从什么时候开始,CCF不再限制选手使用STL,所以在OI赛事中STL被广泛应用. 它分为六个大部分: 1)容器 containers 2)迭代器 iterators 3)空间配置

夏令营讲课内容整理 Day 6 Part 2.

Day 6的第二部分,数论 数论是纯粹数学的分支之一,主要研究整数的性质 1.一些符号: a mod b 代表a除以b得到的余数 a|b a是b的约数 floor(x) 代表x的下取整,即小于等于x的最大整数,也可以认为是直接舍去小数部分 (这个应该是一个符号,但我不知道怎么打出来..下面那个ceil也是) ceil(x) 代表x的上取整,即大于等于x的最小整数,也可以认为是直接舍去小数部分再+1. gcd(a,b) 表示a与b的最大公约数 lcm(a,b) 表示a与b的最小公倍数 累加符号∑

夏令营讲课内容整理 Day 2.

本日主要内容是并查集和堆. 并查集 并查集是一种树型的数据结构,通常用来处理不同集合间的元素之间的合并与查找问题.一个并查集支持三个基本功能:合并.查找和判断.举一个通俗的例子,我和lhz认识,lhz和hzc认识,那么也就可以断定我和hzc认识. 依照并查集的思想,我们把所有要待处理的元素a1,a2,a3....an这n个元素都看作是一个单独的集合,初始状态每个集合都只有一个元素.我们就可以把并查集的合并操作理解为集合之间的取并集操作. 作为一个树形结构,在一个由许多这样的集合构成的森林中,每个

Google C++ 风格指南内容整理

之前一直没有全面的看过Google C++风格指南,现在很多公司进行C++开发都要求按照Google C++风格.在这个网站 http://zh-google-styleguide.readthedocs.org/en/latest/contents/  有人已经把其翻译成中文.为了便于以后查看,下面的内容完全是来自于这个网站,只是把多个网页的内容整理放在了一起. 1.      头文件: 通常每一个.cc文件都有一个对应的.h文件.也有一些常见例外,如单元测试代码和只包含main()函数的.c

网页格式化排版代码,专用信息采集后的内容整理

public static string ClearHtml(string content) { Regex regex = new Regex(""); //首先把p标签的属性去掉,只留<p> regex = new Regex(@"<p.*?>", RegexOptions.IgnoreCase | RegexOptions.Singleline); content = regex.Replace(content, "<p