DS
lamentropetion
---
展开
-
【setDS】牛客练习赛90 D
考虑复杂度,如果一个位置的集合的大小 >= 46了会被删除,因此一个位置的复杂度贡献就是 O(46 * logn),一个位置只能被修改一次,修改的总复杂度就是O(46 * n * logn)我们操作的集合一定是size <= 46的,考虑去维护元素个数 <= 46的集合位置,对于这些位置暴力修改即可。首先有个结论,若元素个数 >= 46,则这堆元素中一定能找出这样的三元组,证明就是斐波那契的极限情况。因此,若询问区间长度 >= 46,则一定能找到,如果不是的话考虑暴力即可。原创 2023-12-20 01:53:13 · 650 阅读 · 0 评论 -
【setDS】牛客小白月赛83 E
我们的答案是一个位置 pos 后面还有多少位置和这个位置的颜色相同,考虑得到这个答案我们需要维护什么东西。首先,一个必要步骤是把它转化为两个序列,这样就变成了一个序列DS问题。用 set 维护位置,剩下就是常规的增删改查了。我们只需要维护颜色之间的边界的位置即可。原创 2023-12-15 23:41:56 · 690 阅读 · 0 评论 -
【字符串】ABC324E
然后因为拼起来之后要包含 t 这个字符串,隐隐约约会感觉到和前缀后缀子序列有关。满足ai + bj >= m有多少对 (i, j),这个直接值域统计一下即可。统计两个指针的方案数一定是枚举一个,统计另一个。退役啦,接下来的博客全是图一乐啦。原创 2023-12-14 00:45:15 · 684 阅读 · 0 评论 -
【离线/并查集】CF1213 G
心血来潮写一下这个*1800的题解,思路一下就出了,但是一开始多了个log被卡了,提醒一下自己。问题是点对的贡献怎么算,很显然可以拆,对于一个连通块,贡献为sz * (sz - 1)这样子 T7了,但是枚举权值就没问题,不知道为什么这样会快,可能是STL的问题....离线的写法还是有讲究的,最好是把答案全部求出来再去O(1)查询,不然容易被卡。排序之后枚举边的权值,就是把边一条条加上去,相当于Kruskal的过程了。之前是 x * (x - 1) / 2,y * (y - 1) / 2。原创 2023-10-20 00:23:29 · 284 阅读 · 0 评论 -
(典题)线段计数 CF690 div3 F
既然存在一条线段和其他所有线段相交,不知道是哪条线段,考虑枚举这条线段,然后计数没有交点的线段个数,取min。对于这个计数是个典,考虑将所有线段的端点扔进vec里,二分计算贡献即可。这题没什么性质可言,可以说就是纯纯的套路题。原创 2023-09-15 00:43:20 · 274 阅读 · 0 评论 -
【DS思想+堆贪心】CF595div3 D2
考虑nlogn做法,先去枚举点,然后把覆盖该点的所有区间扔进优先队列里,优先删除右端点靠右的。大家都说这是典,但是我不懂怎么个典法,可能堆贪心都是这样做的吗,不懂。那怎么看是不是坏点,还得维护一个差分数组,边枚举边维护。首先肯定要贪心,对于一个坏点,优先删除覆盖别的点多的。感觉突破点就是堆贪心。原创 2023-09-08 23:48:55 · 291 阅读 · 0 评论 -
【贪心】CF1779 D
用pre数组记录这个数上次出现的最近位置,用st表判断是否为区间max。如果是,就统计这个元素需要被染色次数,然后比较颜料是否足够即可。难点在于,当一个区间的两端是区间max时,怎么去计算贡献。事实上,只需要考虑这个数上次出现的最近位置即可。还有一点细节就是,不能漏统计最后一段。然后考虑如何去计算贡献。原创 2023-08-15 17:06:42 · 126 阅读 · 0 评论 -
【动态map】牛客挑战赛67 B
在这里,定义{a,b}为cnt1 - cnt0和cnt2 - cnt0。可以先定义一个状态,然后用map统计前缀这个状态的出现次数。当cnt0 和 cnt1都和cnt2相同时,统计贡献。原创 2023-08-13 00:00:35 · 566 阅读 · 0 评论 -
【连通块染色,双指针维护区间map,整除分块】CF616 CDE
很经典的双指针动态维护区间map,用set维护这个元素是否存在以及不同的种类个数,map维护每个元素的出现次数。经典的给格子染色,直接dfs染色就行,不要用并查集,虽然也能做但是不好写。然后对于每一个*,把周围的格子的颜色扔到set里去重统计就行。原创 2023-08-01 19:52:47 · 200 阅读 · 0 评论 -
【树链剖分+MST】CF609E
先把全局的MST求出来,然后对于一条边,如果它本来就在MST中,说明代价就是MST的权值和,否则它加入MST中,此时MST形成了环,我们把环中最大的那条边删掉,就相当于用这条边换掉了环中最大边,这样就是最小权值和。那么怎么求环中最大边,直接树剖即可。原创 2023-07-30 00:20:24 · 228 阅读 · 0 评论 -
【*2400 线段树】CF444 C
一次修改对区间和的贡献不能直接计算,因此我们考虑分开计算贡献,把这个区间分成几个由一种颜色构成的区间,对这些区间去产生贡献。lazy标记的含义是,给这整个区间的颜色赋值为y,那么对区间和的贡献就是abs(x-y),x为原来的颜色。在pushdown时,先去更新左右子区间的标记,然后去更新左右子区间的val,最后清空该区间的tag。在pushdown时,tag永远是为了子区间服务的,在计算本区间的val时不能用本区间的tag。在计算左右子区间的val时,记得用整个区间的tag去计算,为什么呢。原创 2023-07-10 22:33:49 · 262 阅读 · 0 评论 -
【小DS】代码源每日一题div2 上帝的集合
还有一个操作:插入一个数,这个对最小值的影响是什么呢?这个优先队列就解决了,但是麻烦的是询问的时候,我们并没有对其加上add,因此在插入的时候要减去在这个数加入之前的add。那么可以加一个维护的东西:加一个变量add,维护我们对这个集合一共加的值,输出的时候加上add即可。首先看我们需要维护的是什么,是集合中最小的数,这个用优先队列就可以轻松维护。然后去看修改操作对需要维护的东西的影响,全体加上x,那么最小值就+x。原创 2023-06-15 15:22:06 · 58 阅读 · 0 评论 -
【离线】岛屿的数量
记录一下位置就好了,vis记录是否被淹没,如果两边都被淹没过了,那么贡献-1,否则贡献+1。一开始想的是把询问按h排序,把高度也按val排序,这样一个指针扫完就可以了。事实上确实是这么做的,但是我却在答案统计上出了问题,因为岛屿数量和位置有关。手摸了一下发现,淹没山峰的贡献是-1,淹没山谷的贡献是1。因此统计了一下每个深度山峰和山谷的数量,然后离线。然后想的是,既然有关,那就不能把a数组排序。在单指针扫描的基础上进行答案统计就行了。正解是这两种解法的结合版。原创 2023-06-11 21:50:11 · 87 阅读 · 0 评论 -
代码源每日一题div1【离线+树状数组】数数
具体地说,遍历询问的时候,可以用一个指针维护val原创 2023-06-11 11:06:53 · 141 阅读 · 0 评论 -
【枚举+DS】CF1831D
题意:思路:原创 2023-05-29 20:44:07 · 101 阅读 · 0 评论 -
【set维护图】ABC302 E - Isolation
每次操作完问你没连边的点有多少个。op=2时,去掉连接u的所有边。op=1时,连接u和v。原创 2023-05-25 08:55:04 · 64 阅读 · 0 评论 -
【dfs序+线段树】求和
操作2:因为一棵子树对应序列中的一个区间,因此就是用线段树进行区间修改,区间的长度就是子树大小,因此也可以把子树的大小预处理出来。操作1:就是对序列进行单点修改,对u的位置进行修改。树上操作,考虑把树转化为序列,在序列上用DS维护。原创 2023-05-23 19:37:07 · 91 阅读 · 0 评论 -
【dfs序+线段树】P3178 [HAOI2015]树上操作
对于树上的修改操作,我们可以把树的dfs序搞出来,然后在dfs序上修改,这样就把维护树上信息变成维护序列信息了,维护序列的信息用线段树即可。操作1是对一个结点u +val,那就是对这个u的进栈的时间戳,即in[u]位置+val,对out[u]位置-val。操作2是对子树整体+val,那么就相当于对区间整体修改,区间中的数,如果是正的就+val,否则就是-val。注意,这里的dfs序是每个数仅出现2次,即进栈时记录一次,出栈时记录一次。即区间加:(区间中的所有1+区间中的所有-1)*val。原创 2023-05-23 13:48:39 · 534 阅读 · 0 评论 -
【dfn序+DP】树
我们会发现,如果我们按dfn序涂色,在涂每一个点之前,他的父亲祖父等祖先节点肯定都已经先涂过了(这些点的dfn序都比当前点小),他的兄弟节点(也包括各种或近或远的“堂兄弟”节点)和兄弟节点的子树也许也涂过一些。涂这个点无非是两种选择:涂一种新的颜色,或者涂一种已经用过的颜色。而涂一种已经用过的颜色的话,这个点的颜色必须和他父亲的颜色一样,因为这个点到之前的所有点的路径都是要经过它父亲的,如果他和父亲不同色,他和他同色那个点的路径上就不可能所有点颜色都一样,至少他父亲就是不同的。由于有限制:只能用K种颜色。原创 2023-05-22 15:16:50 · 832 阅读 · 0 评论 -
【枚举+sorting+递推(DS思想)】 ABC186 D - Sum of difference
然后注意到相邻两个数的贡献是可以递推的,比较相邻两个数的贡献即可。因为算的是所有对的贡献,因此数列是无序的。O(n^2)超时,肯定是O(n)算。因此可以把数列排个序。原创 2023-05-17 12:39:58 · 73 阅读 · 0 评论 -
【sorting+暴力】CF624div3 C. Perform the Combo
给定一个字符串s和一个数列a,遍历数列a,每次操作都会给字符串前缀的前ai个的元素出现次数++,问你所有操作过后的字符出现次数。注意到操作前后顺序不会变化,且注意到每次回溯是O(n^2)复杂度,因此考虑将a数组sort一下。然后每次操作就相当于前缀这么多字符次数+=前缀这些字符的出现次数 和 新的字符出现次数++排序之后就能用DS维护答案了(有点像莫队?所以还要维护每个字符出现次数的前缀和。原创 2023-05-09 14:19:32 · 59 阅读 · 0 评论 -
对顶堆模板!!【DS对顶堆】ABC281 E - Least Elements
考虑每过去一格,用DS维护前k个元素和sum。每过去一格,删去a[i],添加a[i+m]具体用什么DS呢,取决于我们需要维护什么。我们需要动态维护前k个元素和sum。原创 2023-04-28 23:32:09 · 911 阅读 · 0 评论 -
ABC252 D - Distinct Trio
对于一个三元组,我们去枚举中间那个元素最好,然后比它小的元素和比它大的元素的多少都通过前缀和求出来了。注意到值域很小,我们可以用值域的前缀和来维护全局哈希,即用前缀和来维护多少数比x小,比x大。原创 2023-04-06 23:28:07 · 338 阅读 · 0 评论 -
ABC267 E - Erasing Vertices 2
我们要维护最大值,删去一个点之后,周围所有点的权值都减去中间那个点的权值,这对全局最大值的影响不能直接维护。那就是去考虑线段树了,考虑动态维护一个序列就行,删去一个点之后,修改特定编号的权值,那就是单点修改了,然后。就是先去考虑我们要维护的是什么东西,然后再去考虑修改操作对需要维护的东西的影响。但是如果先删比较小的,大的那个点可能就变小了,贡献也就可能变小。考虑它的操作,删除一个点,点周围所有点的权值都减去a[u]证明的话就是反证法,先删大的点的贡献一定不小于先删小的。这就是DS的含金量!原创 2023-04-07 00:28:17 · 225 阅读 · 0 评论 -
【DS】河南省第十三届ICPC大学生程序设计竞赛 J-甜甜圈
在用线段树和树状数组之前,先去考虑好我们要维护的是哪个序列,我们需要维护的是序列的什么值。每次操作我们找出最大值的位置,贡献加上该最大值头上有几个,然后把它删除。因为他有两根,因此考虑把两根棒合并成一根,然后维护这一根就行。至于怎么去维护贡献,只需要记录上一次删除的位置即可。这样就可以直接维护了,这题用线段树和也可以做!直接模拟复杂度太高,因此考虑用DS优化。对于第一次删除,上一次删除的位置在n。那就是把这两根棒头对头放着就行。对于这道题,首先需要构造序列。我们考虑用树状数组维护。删除其实就是把1变成0。原创 2023-04-14 21:08:10 · 816 阅读 · 0 评论 -
【小DS】ABC253 C - Max - Min Query
操作3就直接输出就行,值得注意的是set最大值和最小值的写法,最大值应该是*prev(S.end()),而不是(*S.end()),end是到不了的。因为是多次删除,怕超时(事实上不会),又要维护它存不存在,因此加个维护的东西:每个数出现的次数。然后考虑修改操作,把min(c,x的次数)的x从集合里删除。操作1就是把原来的erase掉,次数加上去后再insert。首先看需要维护的是什么,是集合里最大值和最小值。操作2就是删除旧的,修改出现次数后换成新的。因为是修改和询问,考虑DS。原创 2023-04-19 00:14:38 · 166 阅读 · 0 评论 -
【小DS】ABC250 E - Prefix Equality
虽然这道题没有明显的修改操作,但是在遍历1~x的时候,每新加一个a[i] or b[i],就相当于是“修改”操作(这是常见的套路)给定两个数组a,b,每次询问两个位置x和y,问a数组前x个构成的集合和b数组前y个构成的集合是不是一样。考虑新加了一个a[i],对“b数组中1~y这些元素在a数组中出现的最晚位置”会产生什么影响呢?设pre_a数组为b[i]在a数组中出现的最晚位置,在遍历过程中维护这个数组。a数组中1~x这些元素在b数组中出现的最晚位置要<=y。a数组中1~x这些元素在b数组中出现的最晚位置。原创 2023-04-23 11:23:17 · 200 阅读 · 0 评论