正睿十一数据结构专题
正睿十一数据结构专题
队列
NOIP2016蚯蚓
首先,先考虑这道题目的暴力做法,用一个堆直接去维护所有的蚯蚓,
但是由于\(m\le 7\times 10^6\)所以肯定过不去
近下来想,对于\(x,y\)两条蚯蚓
如果已经知道\(x>y\)
那么\(x\),\(y\)切完之后,\(x\)切出来的部分一定比\(y\)切出来的对应部分要长
也就是说,单调性是不变的
我们我们就靠两个队列分别维护切出来的部分
再和原队列比较
每次求最大值,打全局tag即可
另外注意初值要尽量大
栈
CF5E
这一道题目,破环为链是关键,问题是怎么破环为链一般破环为链之后我们无法转化为序列问题,也无法去处理重复元素
也就是说,这道题目破环为链不具有一般性
那么我们这道题处理的难点在哪里?环的左右两个方向!
如果这道题在序列上,会好做很多
我们能够把环转化为序列就会好做很多
之后发现,我们把最大值删掉,按顺序做是可以的,最后单独算最大值的贡献即可
因为最大值会阻挡这一方向的所有时限,最大值两边的元素无法通过最大值看到(我们暂时默认元素两两不同)
这样我们就变成了序列上的问题
如果元素两两不同
我们可以直接维护单调栈扫两遍,就可以比较简单的求出所有的贡献
但是元素相同怎么处理?
我们就在单调栈多维护一个值,叫做当前元素的连续出现次数
这样我们强制元素相同的值只能从左向右算贡献
那么就可以处理元素相同的情况,我们在算贡献的时候直接加上该元素的出现次数
最后如果栈里还有元素,答案应该+1而不是加栈顶元素的出现次数
并查集
并查集主要要理解好边带权和扩展域的用法
我们将从一道例题引出这两种写法
noi2001食物链(Luogu2024)
扩展域:
这种关系具有传递性,同时要维护多种关系的时候,一般的合并很难做到这一点
这时候我们要引出扩展域
所谓扩展域,顾名思义,就是将并查集维护的东西进行扩展
此题中,我们不但要维护同类.还要维护吃与被吃
那么我们就把节点\(x\)拆成三个点\(x_{self}\)同类域,\(x_{eat}\)捕食域以及\(x_{enemy}\)天敌域
每次读进来一个同类操作\(x,y\)
我们如果发现\(x_{self}\)和\(y_{eat}\)或者\(x_{self}\)和\(y_{enemy}\)在同一集合
那么这次操作显然不合法
否则
将x,y三个集合一一合并
同理
如果是读入的捕食关系
如果\(x_{self }\)与\(y_{self}\)或者\(x_{enemy}\)与\(y_{self}\)在同一集合
那么不合法
否则,x吃的就是y,x的天敌就是y吃的,x是y的天敌一一合并
边带权
边带权并查集好恶心啊
这是这道题的第二种做法,不需要对并查集进行扩展,我们利用带权并查集解决这个问题
首先,我们并查集维护一下距离
\(x,y\)的距离定义为\(dis_x - dis_y\)我们定义这个值在模\(3\)意义下为\(0\)则代表\(x,y\)是同类,为\(1\)代表\(x\)被\(y\)吃,为\(2\)则代表\(x\)吃\(y\)
我们接下来考虑这种情况
默认大家已经会带权并查集的基本写法
对于\(1\)询问如果\(x,y\)已经在同一集合,那么他们的关系我们可以简单计算出来,并且判断是否合法,如果\(x,y\)不在统一集合,也就是我们要确定他们的关系
也就是说
我们已经知道\(a,b\)现在要把\(f_y\)接到\(f_x\)上
也就是要满足\(a-b-c \equiv 0 \pmod {3}\)
这个还是比较简单的方程
注意一定是把\(f_y\)接到\(f_x\)上
因为如果把\(f_x\)接到\(f_y\)上就不是这个方程了
同理,吃的操作我们也可以这么做
式子变一下就好了
如果理解了上面这东西,这里应该改也不难了
BZOJ3747
线段数题目,我们考虑枚举右端点
考虑右端点右移带来的贡献,左端点只有在\((pre_i,i]\)才有贡献,同时本来在\([pre_{pre_i},pre_i]\)这一部分失去了贡献.
所以我们枚举右端点,每次查询最优的左端点就好了
BZOJ3585
区间mex我们可以得到一个简单的\(n\log {w}\)的算法
直接暴力动态开点套个主席树
之后发现不需要
线段树的叶子结点我们去维护\(i\)出现的最靠右的位置
每次查询\([1,r]\)的主席树的最小值是否比\(l\)小来确定二分方向即可