Tricks(长期更新)

会很杂,尽量分类,每个trick会配题。

难以分类的

难以分类可能只是自己太菜了。

一类断开/分割/etc.相关的问题

考虑时光倒流,改成合并,然后大概率变得好做好想了。

而且合并的时候限制会比正着想少很多,因为随便一种合并的方法都可以对应一种合法的分割方案。

在很多题中都有出现,如DP,贪心,图论等。

曼哈顿距离与切比雪夫距离的转化

对于两点(x1,y1),(x2,y2),曼哈顿距离为|x1x2|+|y1+y2|,切比雪夫距离为max(|x1x2|,|y1y2|)

画图可以发现到原点的曼哈顿距离为1的点形成一个对角线在坐标轴上的正方形,切比雪夫距离为1的点形成一个边与坐标轴平行的正方形。且后一个正方形的边长为前一个的2倍。

我们可以想到二者可以相互转化。

大力推一下:

|x1x2|+|y1y2|=max{(x1x2)+(y1y2),(x2x1)+(y1y2),(x1x2)+(y2y1),(x2x1)+(y2y1)}=max{|(x1+y1)(x2+y2)|,|(x1y1)(x2y2)|}

容易发现这就是(x1+y1,x1y1),(x2+y2,x2y2)两点之间的切比雪夫距离。

max{|x1x2|,|y1y2|}=max{x1+y12x2+y22+x1y12x2y22}

懒得敲完了自己看看吧

容易发现这就是(x1+y12,x1y12),(x2+y22,x2y22)之间的曼哈顿距离。

以上两种转化也可以视作旋转了坐标轴。

[ABC221G] Jumping sequence

给出序列ddi对应着四种操作之一:

  1. (x,y)(x+di,y)

  2. (x,y)(xdi,y)

  3. (x,y)(x,y+di)

  4. (x,y)(x,ydi)

问能否从(0,0)走到(A,B)

考虑换系,将(x,y)转化为(x+y,xy),可以发现xy上的移动相互独立了,每种x±di,y±di的操作都对应原来唯一确定的一种方案。于是对两维分别跑背包即可。

数据刚好比可以搜的范围大一点的

考虑折半搜索,可以把指数砍半(或许可以理解成一种根号?)。

但是也有可能不是折半而另有正解。

图论

生成树

有向图中的内向/外向、最小/最大生成树

别太死板了以为只有无向图最小/最大生成树。

有向图中的内向/外向、最大/最小生成树是类似的。

P2573 [SCOI2012] 滑雪

具有高度对称性的图

咕咕咕。

差分约束

满足构造题的限制

大概率就算看出来也写不了。

就是转化题意后发现每个位置上都会加减一些东西,还要满足结果在一个范围内,那么就列出不等式,尝试差分约束。

树论

depLCA的转化

depLCA(x,y),可以先对x到根的路径上每个点的权值+1,然后查y到根路径上的权值之和。发现这样完全避开了求LCA,可以对更多个数的情况做优化。

P4211 [LNOI2014] LCA

DP

关于单调性

大力分析单调性总是好的。

ai严格单增aii单调不降。类似还有。

关于前缀和

前缀和优化很好,但是定义DP数组时别直接定义前缀和形式的东西。要计算答案时再计算前缀和就好,别急

P9753 [CSP-S 2023] 消消乐

关于字符串上的DP

或许可以当成字符串题做,用一些字符串算法(或者只是思想)结合DP。

长度至少为k的最大子段和

trivial的问题,先钦定一段长度为k的子段要选,然后正常求fi表示[1,i]中钦定选第i个数的最大子段和,然后枚举每个长度为k的区间[l,l+k1],求min(sum+fl1)就好。

钦定必须选某个数k的最大子段和

稍微改动了一点,定义fi,0表示没选k的最大子段和,fi,1表示选了k的最大子段和。然后就有

{fi,0=max(fi1,0+ai,ai),fi,1=fi1,1+aiaikfi,0=inf,fi,1=max(ai,max(fi1,0+ai,fi1,1+ai))ai=k

O(n)DP就好。

求两段的和最大

将两边的最大子段和加起来就行。

就是求出最大子段和后拼起来。

在转移的很多段里面DP的答案不变

把会使答案改变(或者说是会对答案产生贡献/影响)的点单独取出来跑DP。

莫名感觉像虚树(?

可能只是常数优化,但是常数有时也很重要。(不得不提某场校测(2024.10.21 T2)里676的常数导致O(n)过不了。)

定义域和值域互换

类似反函数。就是要求的一个东西值域很小而限制的值域很大,状态数太多了或者不好转,就上反函数。

比较冷门,但很牛。

CF721C

求从1出发,经过的边权和不超过k,最多经过几个点。

发现要是直接把边权扔到状态里就爆了。

于是换一下,设fi,v表示走到i,经过点数为v时的最小边权和。

然后就可以转了,状态数是O(n2)的,再加上拓扑排序和转移,总的也是O(n2)的。

给状态加入更多限制

不好转,就多加限制。

这不一定体现在状态维数的增加,也可以是在状态之外钦定一些东西。

P11233 [CSP-S 2024] 染色(官方数据)

考场上定义了很多种状态,例如考虑fi,0/1表示考虑前i个,第i个填红/蓝的最大得分。但是发现这个状态很无力,对转移很没有帮助。

考虑给状态加入在维度之外的限制。定义fi表示考虑了前i个,钦定i个与第i1个颜色不同的最大得分。

首先答案是fn+1,因为加入了钦定,而第n+1个本来就和第n个不同,且第n+1个无论怎么选贡献都是0,所以是正确的。

然后考虑第i个前面第一个和它颜色相同的位置是j,于是发现在原来的状态中[j+1,i1]贡献难算的问题(不好确定j+1的贡献)解决了:j+1的贡献在fj+1中已经解决了,而[j+2,i1]的贡献是好算的。于是转得动了。

搞掉艾弗森括号

需要分析一点有艾弗森括号的式子的性质,然后化简为繁,再化繁为简。

后面化来化去的或许可以考虑将一坨只带一个真实的变量的式子用一个东西表示,如下文mx

观察值域后也可以考虑将值压到下标上。

P11233 [CSP-S 2024] 染色(官方数据)

还是这道题。

fi表示考虑了前i位,钦定第i位与第i1位颜色不同的最大分数。于是可以写出转移:

fi=max1j<i{fj+w(j+1,i1)+ai[ai=aj1]}

其中[j,i1]是同色段,w(j+1,i1)[j+1,i1]产生的贡献。

我们记si表示[1,i]同色时产生的贡献,于是w可以差分出来。转移方程可以写成:

fi=max1j<i{fj+si1sj+ai[ai=aj1]}=max1j<i{fjsj+ai[ai=aj1]}+si1

我们本来希望尝试记录前缀最大值直接优化,但是发现max中套着艾弗森括号,搞不定。

观察一下,我们发现至少前两项是放在一起的,记pri=fisi

再想想,艾弗森括号成立时,对于这个式子,值肯定比不成立时更大。于是可以对于成立和不成立两种情况分别取max,再合到一起取max

写成式子:

fi=max{max1j<iprj,max1j<iai=aj1prj+ai}+si1

然后前面的那一项就是pr的前缀最大值,拿变量prmx记一下就好了。

对于后面那一个,考虑记mxx=max1j<ix=aj1prj+x。这个东西在每次i往右移之前都要更新,具体的,式子中取j=i时,mxai1=max{mxai1,pri+ai1}

最后,转移就变成了fi=max{prmx,mxai}+si1

以上的转移过程都是O(1)的。状态数O(n),于是总的是O(n)

压缩状态,但不是状压

状态里可以相互推导/具有某种特定联系的,可以尝试去掉其中几个维度。

[ARC073F] Many Moves

第一直觉是定义fi,x,y表示回答完i个询问后,一个棋子在x,一个棋子在y的最小用时。然后发现状态数太多了,哪怕第一维可以滚掉。

继续观察一下,发现回答完第i次询问后,一个棋子一定在xi,另一个棋子不知道。于是修改状态为fi,j表示回答完第i个询问后,一个棋子在xi,另一个棋子在j的最小用时。

考虑转移:

fi,xi1=fi1,j+|jxi|

fi,j=fi1,j+|xixi1|

发现有绝对值,但其实对j的大小分讨就可以拆掉绝对值。根据拆掉后的符号不同,需要维护fi,j+j,fi,jj

状态数还是很大,但是还好。第一种转移只对于一个位置改,第二种转移是对所有状态加上常数。于是上线段树,维护全局加,单点修,单点查就好。

矩阵优化

直观地可以看到状态中有一维范围很大,于是把这一维放到矩阵中递推,然后上快速幂。同时可能有多次询问。

状态数/转移数的优化

手玩一下发现转移其实很少/状态其实很少,就都存下来,再去跑。

关于排列的定义域和值域

其实会发现这两个东西很模糊,因为都是从1n的。在原来的序列上想不动的时候就可以转化题意放到值域上想(给每个值分配一个下标之类的)。

转移过程中会遇到特殊点/特殊限制

在特殊点处停下来,特殊转移一下,再继续跑。

二分

中位数

二分一个mid,大于等于它的数换成1,小于它的数换成1,查询和是否大于等于0

二分hash

同字符串。什么字符串技巧都不会的时候,会这个就够了。

字符串

比较两个字符串的大小

二分+hash求LCP,然后比较后面那个字符,是O(logn)的。

结合倍增

跳border的时候可能会跳很多次,用倍增的思想可以优化至log

如用类似ST表一样的思路,定义sti,j表示从i开始跳2j次border可以到的位置,然后就可以倍增起来。

对KMP的改造

有时可能要求最短border。考虑在KMP的过程中递推这个东西。

gi表示[1,i]的最短border,若为0,将gi设为i,这样可能会方便解决问题。

i处我们求出faili=j后,进行讨论:

  • j>0时,若failj>0,则gi=gfailj;若failj=0,则gi=j

  • j=0时,gi=i

特别的,fail1=0g1=1

构造/Ad-hoc

关于图的形态的构造

多尝试特殊形态的图,记录一下:

  • 菊花图

  • 链套菊花

  • 基环树

  • 网格图

(2024.10.23 T1就是先考虑链,然后对链调整,改造成链套菊花。)

数学

发现联考T1都放聪明的数学题,感觉需要记录一下。

二进制相关

二进制下找因子

听上去就很扯淡。

但是这是真的。

发现lowbit(x)一定是x的因子。

数论相关

余数找环

注意到aφ(m)1(modm)(am),那么当am时,环长一定是φ(m)的一个因数。然后枚举去找。(来自2024.9.30数学测试)

和式相关

最大化一段前缀与一段子段的和

最大化i=1qai+k=stak,其中q,s,t是待定的参数。

有个结论:[1,q][s,t]要么包含,要么无交。

可以反证,设sq<t,那么由于最大化了i=1qai,可知区间[q+1,t]的和非正,于是t=q时一定不比此刻更劣,所以得证。

并且还可以加强一下,当包含的时候,一定有t=q,这是显然的。因为若t<q,当[t+1,q]的和小于0时,q的最大性不成立,而当[t+1,q]的和大于等于0时,使t=q一定不会更劣。得证。

在一次比赛中(2024.11.25),出题人加上了需要保证s>q或者tq的限制,但由于以上结论,这个限制是废的。

分治

求关于每个区间的信息

发现这种都可以考虑分治。是很好的思考方向。

求出每个区间的最大前缀和之和

上接最大化一段前缀和一段子段的和。

要求出每个区间的最大前缀的和。这里前缀可以取一段空前缀,即一个区间的最大前缀和可以为0

记前缀和si=k=1iak,考虑枚举一下左端点l,那么对于一个右端点,这段区间的贡献就是maxk=lrsksl1

从大到小枚举l,同时维护一个单调栈TT内部从栈顶到栈底满足sTi单调递增,Ti存的是原数组的下标。

那么对于一个确定的l,我们要统计所有rl的区间的贡献。考虑二分出第一个Ti使得sTisl1,这样在Ti之前的r是没有贡献的。对于一个位置Ti,右端点落在[Ti,Ti1)中的区间的贡献为sTi(Ti1Ti)sl1(Ti1Ti)。那么总的贡献为j=1isTj(TjTj1)sl1(nTi+1)。移动l时,T中的贡献只有弹出去的部分和加入的一个点的部分会改变。记一下栈中的前缀和,每次加入一个点只需更新一处。统计贡献就二分一下,然后直接查。总的是O(nlogn)

求出每个区间的最大子段和之和

上接最大化一段前缀和一段子段的和。

以及上接求出每个区间的最大前缀的和。

发现单调栈的做法不太好延续过来,遂放弃。

考虑分治(因为区间的最大子段和就是考虑分治)。现已分治到[L,R],再分治到[L,mid][mid+1,R]。现在要算的就是左端点l[L,mid],右端点在[mid+1,R]的区间的最大子段和之和。

考虑对于每个在[L,mid]中的i,求出[i,mid]的最大子段和fi以及最大后缀和gi;对于每个在[mid+1,R]中的i,求出[mid+1,i]的最大子段和fi以及最大前缀和gi

考虑从midLl,对每个l计算贡献。设右端点为r,则[l,r]的贡献为max{fl,fr,gl+gr}。可以注意到r递增,l不变时frgl+gr单调不降,l继续向左扫时fl单调不降且可以证明flgl仍然大于grfl>gl+gr(就是下面的结论),于是可以用一个指针扫出fl>max{fr,gl+gr}r所在的前缀。这个的贡献直接乘一下就好了。

然后考虑gl+gr>fr的做法。移项得到frgr<gl,发现fg是单调不降的。有单调性之后又可以双指针一下,就好做了。现在来证明这个单调性。

gi视作最大前缀和,它的端点为k,它后缀和时证明是相同的。由最大化一段前缀和一段子段的和的结论,fi的端点lr只有两种情况:要么r=k,要么l>k

现在考虑在已经处理出figi的序列后加入一个数字ai+1

考虑第一种r=k时,那么如果此时最大前缀和变化,则必然是所有数的和大于gi,于是[k+1,i+1]的和大于0,此时最大子段和也一定会加上[k+1,i+1]这一段。于是最大前缀和与最大子段和的变化量相同。f的变化量不小于g的变化量。

考虑第二种l>k时,如果此时最大前缀和变化,则同上,[k+1,i+1]的和大于0。而由于l>k,所以[k+1,r]的和是小于等于0的。于是[r+1,i+1]的和大于[k+1,i+1]的和,于是f的变化量不小于g的变化量。

综上,fg单调不降。

挂个原题:Treasure Hunt

DS

posted @   RandomShuffle  阅读(19)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示