一些数据结构维护手法,好题

一些数据结构维护手法,好题

[蓝桥杯 2022 国 AC] 替换字符

发现字母的变换有复合性质,可以用线段树维护一个 lazy[26] 数组表示这个区间的每一个字母变成了那一个。

当两个标记合并的时候有:nwlazy[i]=blazy[alazy[i]],相当于标记信息的复合。


One Occurrence

对于这种某个数只出现一次的经典题,考虑一个经典的 trick,我们维护一个 pre[i] 表示 ai 上一次出现的位置,然后 suf[i] 表示 ai 下一次出现的位置。

我们发现若 ai 在区间 [l,r] 中只出现了一次 pre[i]<l or suf[i]>r

我们发现这样我们不好处理,因为多了个 suf 的情况,我们不难想到如果能固定 r,是不是问题就好解决了。

利用扫描线思想,我们把询问离线下来,扫 r, 然后去维护 l 的答案。

我们用一个线段树,维护区间 pre[i] 的最小值。

对于扫到某个位置 r,我们把 r 这个位置在线段树中的值改为 pre[r],然后注意此时还要把 pre[r] 位置的值改为 INF,因为此时如果 pre[r] 位置的数的 pre 是满足条件的,但又因为在 r 处还出现了一次,所以此时他在所有以 r 为右端点的询问中,一定是不合法的,所以我们要改为 INF


A Simple Task

题目要求我们对区间的所有字母排序(升序或者降序),我们不难发现其实本质就是按 26 个字母的顺序依次给区间赋值。

每次区间修改就是遍历 26 个字母,在其对应的线段树上修改。

所以我们可以用线段树维护每种字母的出现次数。

故我们开 26 个线段树,每颗线段树维护对应字母的出现次数,然后支持区间赋值即可。


laoya 的有根树

很容易想到离线,我们可以先把整颗树建好,那么增加一个点和删除一个点,都相当于在树上修改权值,当一个叶子被删除的时候,其到根结点上的整条链上的 g 值都要减少,增加也是同理。

对于 g(i)×g(j) 的最大值,我们不难想到当 g(i),g(j) 取最大两个,或者取最小两个的时候可以得到最优解。

所以我们不难想到维护树上的最大,次大,最小,次小。

而且还要支持子树查询,链上修改。

我们很容易想到树链剖分+线段树维护。(这里要注意边界,例如当子树内只有一个数的时候,次大和次小是不存在的,要弄成无穷,当增加或者删除的时候,要注意边界的修改)


数组划分

考虑没有修改怎么做,我们可以仿照最大字段和的思路,令 fi 为以 i 为右端点的最大美值,gi 表示前缀 1ifi 的最大值。

不难得到如下转移方程:

  • fi=max(fi1+ai,fi2+3×ai2×ai1,ai,3×ai2×ai1)
  • gi=max(gi1,fi)

然后考虑修改,这是一个经典的动态 DP,我们把 DP 的转移看成一个max+矩阵,直接用线段树维护即可。

[fi2fi1gi100]×[inf3ai2ai23ai2ai2infinf0aiaiinfinfinfinf0infinfinfaiai0infinf3ai2ai13ai2ai1inf0]=[fi1figi00]

每次单点修改,相当于修改与 ai 有关的系数矩阵:AiAi+1

最后答案就为:[infinfinf00]×A(其中 A 即为整个区间的矩阵)。

posted @   jackle  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示