一.写在前面
如果说廿四10天集训,对于我,是完成了从入门到蒟蒻的蜕变,那么,HL7天,可以说是真正成为了OIer,虽然是被小学生、初中生(南方的)薄纱的那种高中OIer……
二.目录
Day 1:周赛一
Day 2:基础数据结构
Day 3:树状数组和线段树
Day 4:倍增问题
Day 5:字符串
Day 6:根号问题+杂选
Day 7:周赛二
好好好,都是我最弱的……
三.知识
我在我的日祭中写道,会在最后的总结中对知识进行汇总,我来兑现我的诺言了。
Day1:寄储数据结构
对,存储我寄的结构
个人认为STL 一直是我最烂的部分(与之相反的是数论)
是我不爱背板子吗?
好像不是,毕竟文化课我都挺过来了。
但是又感觉STL跟背没关系。
如果背为主,信息怎为理科?
但是总是要面对的啊!
我要承认困难,我要客服困难!
当天的题就不写了,主要写写新知识——笛卡尔树(实在没想到一个理论数学家又和OI有关系了@欧拉先生)
首先要明确笛卡尔树是二叉树!如果这点忘的话很可能构树时会RE(别问我怎么知道的)
定义(stO OIWiki):
笛卡尔树是一种二叉树,每一个结点由一个键值二元组 (k,w) 构成。要求 k 满足二叉搜索树的性质,而 w 满足堆的性质。一个有趣的事实是,如果笛卡尔树的 k,w 键值确定,且 k 互不相同,w 互不相同,那么这个笛卡尔树的结构是唯一的。
即:
在一棵笛卡尔树中,定义根节点是所有的元素中数值最小的那一个元素。笛卡尔树中每一个节点可以有 0,1,2 个节点。
对于根节点,假设它在原数组中左边不存在任何的一个元素,那么根节点就是没有左儿子的,否则,根节点的左儿子就是它在原数组中左边的所有元素中数值最小的那一个节点;右儿子同理,如果根节点在原数组中左边不存在任何的一个元素,那么根节点就是没有右儿子的,否则,根节点的右儿子就是它在原数组中右边所有的元素中数值最小的那一个点。对于一个非根节点,建立其左右儿子的步骤和对于根节点建立左右儿子的步骤是完全相同的。
性质(部分来源于Google):
构建
不能比OIWiki写的更明白了!
新建一个大小为 n 的空栈。用 top 来标操作前的栈顶,k 来标记当前栈顶。
For i := 1 to n
k := top
While 栈非空 且 栈顶元素 > 当前元素
k--
if 栈非空
栈顶元素.右儿子 := 当前元素
if k < top
当前元素.左儿子 := 上一个被弹出的元素
当前元素入栈
top := k
for (int i=1;i<=n;i++)
{
int k=top;
while(k>0&&h[stk[k]]>h[i])
k--;
if(k)
rs[stk[k]]=i; // rs代表笛卡尔树每个节点的右儿子
if(k<top)
ls[i]=stk[k+1]; // ls代表笛卡尔树每个节点的左儿子
stk[k++]=i;
top=k;
}
板子传送门:Problem - 1506 (hdu.edu.cn)
Day2:
原谅我的懒惰,但是一看就懂,一懂就会的好资源为什么不用呢:
树状数组 - OI Wiki (oi-wiki.org)
线段树 - OI Wiki (oi-wiki.org)
Day3:
倍增
以下为正确理解个人理解:
倍增算法,顾名思义,就是不断地翻倍。
虽然是一种基础算法,但它能够使得线性的处理转化为对数级的处理,大大地优化时间复杂度,在很多算法中都有应用,其中最常见的就是ST表以及LCA(树上最近公共祖先)(在本part中无其他含义)了。
个人在网上找了个例题,感觉易于理解(不戳)!
有一个环状的操场,操场被分割为 [1,n] 个小块,每个小块上写着一个数字。
有一只小白兔站在操场的起点,它每次可以跳 k 个小块,然后拿走等同于它所站小块上数字数量的胡萝卜,问它跳 m次,总共可以拿到几个胡萝卜?
如果能够算出来的话,小白兔就能把所有的胡萝卜都带回家吃啦!