OI题目模型记录

不定时更新(遇到一道好题就会更新)

转换法

有一些题的操作难以实现,这时可以考虑转换法。

  1. P7735 [NOI2021] 轻重边

本题的修改操作较难,故让它第i次修改只是把两点路径上的点染成i颜色。

可以发现,若一条边两点颜色相同,则该边为重边,否则为轻边。

那么询问就变成路径上有几个不同颜色段,用树链剖分+线段树即可,O(nlog2n)

  1. CF1334G Substring Search

sitj匹配需要si=tjsi=p(tj)

转化为(sitj)(sip(tj))=0,即si2sitjsip(tj)+tjp(tj)=0

整个字符串匹配成功可以转化为i=1|S|(si2sitj+i1sip(tj+i1)+tj+i1p(tj+i1))2=0

i=1|S|(si2si(tj+i1+p(tj+i1))+tj+i1p(tj+i1))2=i=1|S|si42(tj+i1+p(tj+i1))si3+((tj+i1+p(tj+i1))2+2(tj+i1p(tj+i1))si22(tj+i1+p(tj+i1))tj+i1p(tj+i1)si+(tj+i1p(tj+i1))2

将s翻转后即可转化为卷积形式,用NTT可以达到O(nlogn)

  1. P3204 [HNOI2010]公交线路

可以转换为:

  1. 在长度为n的序列里填数,可以填[1,k]内的数
  2. k个满足第i个填的是i
  3. 最后k个为[1,k]的排列
  4. 每个长度为p的区间内要包含[1,k]中的所有数

fi,S表示前i1个车站已经填完,S[i,i+P1]是否填过的状态 时的方案数

fi,S+=fi1,S(S2S,S&1=1,popcount(S)=popcount(S)=k)

为了保证每个都填,S&1必须为1,即第i1位一定要填

为了保证满足限制4,我们强制转移时[i1,i+P2][i,i+P1]都满足[1,k]各填了一个,所以popcount(S)=popcount(S)=k

转移的含义:让S中新填的数和第i1位填的数一样。

初始状态为f1,2k1,答案状态为fnk+1,2k1

可以发现状态数为Cp1k1C95=126,可以使用矩阵快速幂优化,时间复杂度O((Cp1k1)3logn)

  1. 某题

非空正整数数列{am}满足k,ak2h(n)表示满足k=1mam=n的序列个数,求k=2nk×h(k),2n3.5×107

h(i)很难算,所以考虑转换答案:

k×h(k)就是乘积为k的序列的乘积之和,所以答案就是乘积在[2,n]范围内的序列的乘积之和。

fi表示乘积在[2,i]的序列的乘积之和,则有转移方程:

fi=1+d=2id×fid(算上空序列)

答案为fn1

因为nab=nab,所以所有要算的状态都可以表示为nx的形式

用整除分块优化可以达到时间复杂度O(n0.75),空间复杂度O(n)

  1. [ARC110E] Shorten ABC

ABC 分别替换为 123,可以发现一次操作后整个序列的异或和是不变的。

然后由原串 S 得到的新串 T 有个性质:T 的每个字符都对应 S 串的一段区间。

一个区间可以操作成一个字符,要满足下列两个条件之一:

  1. 长度为一
  2. 异或和不为零且包含的字符不全部相同

为了防止算重,每次只选长度最短的区间计算即可。

fi 表示 [1,i] 能得到的序列总数,gi,j 表示 i 为左端点,对应字符为 j 的最短区间的长度。

gi,j={1j=aigi+1,jai+1jai

fifi+gi+1,j

建图优化

当图的边数过多时,用各种方法减少边的数量。

  1. P6378 [PA2010] Riddle

明显的2-SAT问题,但是每个大小为w的部分要建w2条边,于是用前缀和建图。

原本第i个点有:是/非关键点两种(记为ai,1ai,0),都要维护一个前缀(记为si,1si,0),再按2-SAT建边。

之后就能把边的个数降为线性。

  1. P6822 [PA2012]Tax

较大值条件难以处理,考虑重新建图。

可以把点看做边,边看做点。但是边又变成n2级别。

之后把原图中的同一点的出边(单向)按边权排序,并且前缀和建图。

排序后第i条原单向边为ui权值为wi,其反边为vi

uiui+1,边权为wi+1wi

uiui+1,边权为0

viui,边权为wi

这样就实现了较大值并且少了边,之后新开源点和汇点处理起始就可以跑最短路了。

  1. P3783 [SDOI2017]天才黑客

题意:

一条有向路径的长度为这条路径上每个边的边权之和+按照路径的顺序将这些边上的字符串排成一列,相邻两个串的lcp长度之和。求有向图中1号点到其他点的最短路。

和P6822 [PA2012]Tax 很像的一道题,由于lcp长度长度难以处理,所以把点看做边,边看做点。

例如ei:awi,sib,ej:bwj,sjc

就连成:aiwibilcp(si,sj)ajwjbj

可以发现中间的边是O(m2)的,考虑前缀和优化。

在字典树上有:(用F[l,r]表示mink=dfn[l]dfn[r]dep[k])

lcp(si,sj)=dep[lca(si,sj)]=F[si,sj]

假设要连出边的点的集合为b1,2,,k1,要连入点的集合为a1,2,,k2(都按字典树的dfn排序了)

那么我们只要bi0bi+1,ci0ci+1bilcp(bi,chi)chi,bgilcp(gi,ci)ci就能实现让bilcp(bi,cj)cj(jhi)了。

其中hi指最小的j使得dfn[cj]dfn[bi],gi指最大的j使得dfn[bj]dfn[ci]

原理是这样的:F[bi,cj](jhi)=min{mink=ibghF[bk,chk],mink=hijF[bgk,ck]}(这些区间都包含在[bi,cj]内)

这样只向dfn更大的连了边,所以要把ei拆成四个点ai,0/1,bi,0/1并连四条边:ai,jwi,sibi,k(j,k{0,1}),之后对于bi,0ai,0的连dfn更大的,对于bi,1ai,1的连dfn更小的就行了。

新图点的个数和边的个数都是差不多4n,时间复杂度为O(nlogn)

  1. P5471 [NOI2019] 弹跳

h=1就是典型的线段树建图,所以可以想到线段树套线段树优化建图。

但是本题的点非常少,所以我们考虑用线段树套平衡树(set)来减少空间。

众所周知,dijkstra算法有一个优秀的性质:每个点只会被标记一次,并且权值非负。

在有多个矩形覆盖一个点的时候,我们肯定是用dis最小的矩形来覆盖。

所以我们可以把每个弹跳装置也看做一个点,跑dijkstra的时候就可以保证每个点都是被最优的矩形所覆盖,所以覆盖过一次的节点可以删去。

时间复杂度O(nlog2n+(n+m)log(n+m)),空间复杂度O(nlogn)

  1. P7712 [Ynoi2077] hlcpq

将水平线段的 l,r 都加上 n,加边限制变成:x,y 有连边当且仅当 lxyrx,lyxry

考虑 tarjan 算法的过程,递归到 u 时,枚举边 (u,v),若 v 没遍历过则需要递归,否则更新 low[u]dfn[v]

递归的部分可以 O(n) 枚举,更新则是需要求最小值。

所以用主席树维护未访问过的点个数、访问过的点的 dfn 最小值。

修改点为已访问,只需要改对应的叶节点。在找未访问点时,要么找到有效点,要么更新个数为 0,是均摊 O(nlogn) 的。

矩阵乘法

将一些操作转化成矩阵乘法后,可以利用结合律将其优化至O(logn)的计算复杂度

  1. P1939 【模板】矩阵加速(数列)

[fifi1fi2]=[101100010][fi1fi2fi3]

  1. P3263 [JLOI2015]有意义的字符串

bd2,b+d2x2bx+b2d4=0的两根。

柿子可以化为xn=bxn1+db24xn2,而且db24还是整数。

fi=(bd2)i+(b+d2)i,则有fi=bfi1+db24fi2

[fifi1]=[bdb2410][fi1fi2]

n为偶时,0<(bd2)n<1

n为奇时,1<(bd2)n<0

最后输出时判断奇偶即可

  1. P3193 [HNOI2008]GT考试

f[i][j]+=f[i1][k](匹配到第k位后加一个字符能匹配到第j位,0j,k<m

构造矩阵A(只有A0,0=1),矩阵B,对于每个满足上述条件的(j,k),让Bi,j=1,其余为0

之后计算A×Bn就行。

差不多的一题:见转换法T3:P3204 [HNOI2010]公交线路

  1. P6772 [NOI2020] 美食家

f[t+w][u][v]=max{f[t][u][p]+G[p][v]}(pw,G[p][v]v)

由于w5,把边可以拆成5条长度为1的边,之后变成

f[t+1][u][v]=max{f[t][u][p]+G[p][v]}(pv)

定义广义矩阵乘法C=AB(可以证明有结合律):

Ci,j=maxk{Ai,k+Bk,j}

令原图邻接矩阵为G,则f[t]=f[0]Gt

A来维护ans[1]

然后只要把美食节按时间排序,之后就对于每个1ik

AAGtiti1,A[xi]A[xi]+yi

就可以维护每个美食节。

预处理G2z次幂(z为整数),由于点的个数为5n,时间复杂度为O(k(5n)2logT+(5n)3logT)

  1. P6569 [NOI Online #3 提高组] 魔法值

发现ai很大,n,q很小,就可以发现矩阵乘法的时间复杂度应该是对的。

定义矩阵异或(我自己这么叫)为:

(AB)i,j=xorkAi,k×Bk,j

看看有没有结合律吧:

ABC

=xork(AB)i,k×Ck,j

=xork(xordAi,d×Bd,k)×Ck,j

乍眼一看就知道没有结合律,但是本题中B,C01矩阵,还可以进行进一步化简:

上述柿子中Ai,d一共异或了kBd,k×Ck,j次,所以上述式子可以化为

xordAi,d×((kBd,k×Ck,j)&1)

=xordAi,d×(xorkBd,k×Ck,j)

也就是说,当B,C01矩阵时是有结合律的。

预处理邻接矩阵的2z次幂(z为整数),计算答案时只计算第一列。

此时答案为第一行第一列的数,时间复杂度O((n+q)n2logai)

  1. P3328 [SDOI2015]音质检测

加一矩阵:[FiFi11]=[1ab100100][Fi1Fi21]

减一矩阵:a0时,[Fi1Fi21]=[0101a1aba001][FiFi11]

a=0时,[Fi1Fi21]=[01001b001][FiFi11]

V(i)=[FiFi11],那么第i项的值就是V(Ai1+1)V(Ai1+1)[0][0]

由于是矩阵[0][0]位置的值,我们算(V(Ai1+1)V(Ai1+1)T)[0][0]也不影响答案,而且有:

(G×V(Ai1+1))((G×V(Ai1+1))T)=G×V(Ai1+1)V(Ai1+1)T×GT,这样我们线段树部分就不会被乘法顺序影响了。

用线段树维护区间矩阵和,支持在前或后乘一个新矩阵即可,时间复杂度O(nlogn)

  1. P7739 [NOI2021] 密码箱

看到它求值的部分是算多次a+1b,于是考虑把它换成矩阵运算使得它能O(logn)修改。

[ba]表示ab,那么计算a+1bc就可以变成

[bab+c]=[011a][cb]

答案就可以表示成[011a0][011a1][011ak]

然后发现W操作就是使[011ak]变成[011ak+1]

可以变成多乘一个[1101]

然后可以发现E操作就是多乘一个[0112]

用平衡树维护修改达到O(nlogn)即可

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