近期总结(? ~ 3.9)

这篇博客探讨了在解决计算机科学问题时如何利用数据结构和算法进行优化。作者提到了几种策略,如利用空间或时间限制避免暴力算法,使用启发式方法,树剖、线段树和LCT( Lowest Common Ancestor)等数据结构优化树上问题,以及通过决策单调性优化DP转移。此外,还介绍了势能分析的概念,用于减少边的检查次数。博主计划进一步学习圆方树、AC自动机和网络流等技术,并设定了每日学习和练习的目标。
摘要由CSDN通过智能技术生成

数据结构

势能分析

注意到一些空间或时间的限制,使得一些 “暴力” 算法时空合法。
比如:
1.一个点最多会被考虑到多少次,从而往启发式的方向思考。
2.在树上把询问离线挂在点上, d f s dfs dfs 时直接跑轻儿子统计答案,详见蜘蛛爬树。
3.吉如一线段树
4.多利用树剖重儿子的优秀性质,以及 s e t set set 的优秀性质,去维护一些加入和修改一一对应的操作。
5.对于若干段需要分开求的答案,但求完之后可以合并的题目,考虑这相当于染色,然后套用 l c t lct lct a c c e s s access access 的时间复杂度。
例: D T O J 4734 ( l c t + s a m ) DTOJ4734(lct+sam) DTOJ4734(lct+sam)
考虑把 s a m sam sam 建出来,容斥计算答案,对于每次新增的子串 s [ 1 , i ] , s [ 2 , i ] … s [ l e n i , i ] s[1,i],s[2,i] \dots s[len_i,i] s[1,i],s[2,i]s[leni,i],计算有多少子串属于它。
我们这样考虑:如果我们知道每个子串的最后出现位置的左端点,那么我们就能够统计答案。
所以问题转化为如何去维护每个子串的出现位置的左端点的线段树。
显然,更新了位置 i i i 之后,子串 s [ 1 , i ] , s [ 2 , i ] , … , s [ i , i ] s[1,i],s[2,i],\dots,s[i,i] s[1,i],s[2,i],,s[i,i],的最后出现位置一定是 1 , 2 , … , i 1,2,\dots,i 1,2,,i,所以对于区间 [ 1 , i ] [1,i] [1,i] 1 1 1 即可,然后我们还要把一些出现过的子串对应的区间给扣掉,这些子串显然在 p a r e n t parent parent 树上新增节点的祖先上,暴力跳链去修改的复杂度显然是错的,但是我们注意到一点,当一条链被暴力修改之后,这些子串最后出现位置的右端点一定是 i i i,他们的左端点就一定是连续的,这就相当于下次用到这条链时,这若干个点的答案可以统一计算,这像极了什么?没错就是 l c t lct lct 中的 a c c e s s access access 操作。然后根据 l c t lct lct 的复杂度即可证明该复杂度正确,用 l c t lct lct 的方式去做即可。

6.多注意题目中非常小的变量,从值域/定义域的角度去优化。
例: D T O J 4919 DTOJ4919 DTOJ4919

考虑去维护每个点的超集,暴力去维护,然后注意到 k k k 非常小,然后转移过程又是 D A G DAG DAG 所以每次检索到的点的出现次数如果大于 m a x { k } max\{k\} max{k} 就返回,这样效率就从 O ( n 2 ) O(n^2) O(n2) 优化到 O ( n k ) O(nk) O(nk) 了。

统计答案

对于一些操作,有些好维护,有些不好直接维护。我们对于不好直接维护的答案考虑从其他角度去维护它。(并不一定需要及时维护)。

例: D T O J 4926 DTOJ4926 DTOJ4926

d i s t ( i , j ) = d j + d i − 2 × d l c a ( i , j ) dist(i,j)=d_j+d_i-2 \times d_{lca(i,j)} dist(i,j)=dj+di2×dlca(i,j),对于一个固定的 j j j,我们在 d f s dfs dfs 序上可以很好地维护 d j , d i d_j,d_i dj,di的答案,但是 l c a lca lca 的贡献不好维护,我们这样考虑:
首先考虑树剖,从 y y y 开始往 x x x 跳,对于 l c a lca lca i i i 的贡献,我们在询问的时候再去计算这个答案。详细地说,我们询问的时候并不关心是哪些点的答案和,我们只关心总的答案和,又因为该答案在 i i i 处好统计,在 j j j 处不好统计,所以我们询问时只需要知道又多少重链上的点查询了多少其轻儿子树,维护子树和以及询问时往根节点跳重链即可。

dp转移相关

决策单调性

有些 d p dp dp,当 i < j i<j i<j 且从 j j j 转移比从 i i i 转移更优时, i i i 就不可能成为答案了,也就是说——决策点满足单调性。其中,一个决策点 i i i 的最优区间一定是连续的且不同决策点的区间不重不漏覆盖了 [ 1 , n ] [1,n] [1,n],那么这种时候我们就可以根据其性质去优化。

换而言之,就是去维护 “最优区间”,维护一段一段区间的最优决策点。
查询 i i i 的更新时,直接查询 i i i 的最优决策点即可,然后把决策点 i i i 插入更新最优区间。
我们细说后者,我们根据性质去考虑每一段区间的最优决策点 j j j,然后对于 i i i 我们可以求出一个分界点 k k k,使得 [ 1 , k ] [1,k] [1,k] [ k + 1 , n ] [k+1,n] [k+1,n] 分别有一个更优的点,然后根据此去更新维护最优区间的栈即可。

势能(另)

例: D T O J 5899 DTOJ5899 DTOJ5899

一个朴素的想法是启发式合并,然后暴力遍历出边寻找答案,每条边最多会被加入一次,而会被检查多次,这样显然时间是很浪费的。所以我们要想一个办法,让符合条件的边被检查到或者说,减少一条边被检查到的次数。

重新审视一下我们需要什么:我们需要设置一个选边的标准,使其满足:
1.从点出发遍历。
2.每次需要重新设置,使其在两个端点上都不满足,并且该次数较小( l o g n ? n ? log n? \sqrt n ? logn?n ? )。

因为与两个点有关,判定条件是对于边 e : ( i , j ) e:(i,j) e:(i,j),满足 a i + a j ≥ w e a_i+a_j \geq w_e ai+ajwe,所以这里有一个经典操作(套路),用 a i + a j a_i+a_j ai+aj 的和与 w e w_e we 的差值的一半加在两个电上作为阈值,即 i i i 处的阈值为 a i + w e − a i − a j 2 a_i+ \frac{w_e-a_i-a_j}{2} ai+2weaiaj j j j 处的阈值为 a j + w e − a i − a j 2 a_j+ \frac{w_e-a_i-a_j}{2} aj+2weaiaj。这样每次只有达到阈值才检查该条边,若不满足,则再重新赋值两个点的阈值,这样就又都不满足阈值了,可以证明,最多不满足 l o g log log 次,然后就成功的优化了效率。

暂时就到这里,最近就学了这些东西。faq

接下来准备做的事:
1.学圆方树
2.复习 a c ac ac 自动机,马拉车。
3.一天一道数据结构(题单 o r or or 洛谷)
4.生成函数(优先级最低)
5.网络流刷题
6.每天 3 3 3 道测试题一定补完。
7.每天 12 12 12 点前一定睡觉。

暂时就这些。 希望不要咕了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值