正睿十一数据结构专题

正睿十一数据结构专题

队列

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\)小来确定二分方向即可

posted @ 2019-10-08 20:22  wyxdrqcccc  阅读(123)  评论(0编辑  收藏  举报