2023.05 做题记录

五月第一题,是 Ynoi!虽然这题基本没有 Ynoi 的感觉。

考虑对于一个集合 S={x1,x2xn} 计算所有子集的方差之和,首先可以得到

f(S)=i=1n(i1)(n1i1)i2i=1nxi22i=2n(n2i2)i21i<jnxixj

由经典的组合数恒等式 (mk)(nm)=(nk)(nkmk),得到 (i1)(n1i1)=(n1)(n2i2)

带回得到

f(S)=i=2n(n2i2)i2((n1)i=1nxi221i<jnxixj)

f(S)=i=2n(n2i2)i2(ni=1nxi2(i=1nxi)2)

后面两个东西是好维护的,可以用线段树搞定:维护区间和以及平方和就行了。

前面这个东西还要继续化简。记 gn=i=2n(n2i2)i2,把 1n(n1) 提出来,得到 gn=2n1i=1n(ni)in(n1)

最后一步就是求 i=1n(ni)i,可以 OEIS,得到 A103213,递推式是 a(n+4) = 2*(n+3)*(n+2)^2*a(n+1)-(n+3)*(13+5*n)*a(n+2)+(4*n+13)*a(n+3),这样就可以算出 gn 了。

总时间复杂度 O(nlogn),有点卡空间,注意开 int,开 int 之后取模乘法不要直接乘。

  • ARC077F SS 【kmp,字符串,border 理论】

TS 减去了 border 之后的字符串。

|S|=k|T| 的时候,会得到:SSSTSTSTTSTTSTTTSTTT,考虑到操作次数可以视为无穷多,那么只需要观察前一半。差分之后,形如 STTTT 的是很好算的,经过一半的 T 要特殊处理。

|S|k|T| 的时候,会得到:SSSTSTSTSSTSSTSSTSTSST,观察前一半,发现是斐波那契串,可以搞出前若干项然后数,还是比较好做的。

时间复杂度 O(|S|+log)

修改显然是个不好做的东西,但是这玩意儿和连续段相关,考虑预处理前后缀答案然后拼起来。

s 表示前缀和,fi=max{fi1,maxj=1i1(ij)(ij+1)2(sisj)}

这个式子拆开来,按照是否和 ij 相关就可以斜率优化了,用单调栈做。

倒过来的话是相同的,可以如法炮制。

你以为做完了吗?显然不是啊,还有经过修改位置的情况。这个也可以考虑预处理,用分治的方法优化 dp,用单调栈维护上凸壳,复杂度 O(nlogn)

总时间复杂度 O(nlogn)

首先这个 k 个约束可以通过在 ACAM 上状压 dp 解决。

接下来是 LCS 的问题,这里可以采用子序列自动机,记录一下两个串的所在位置。

状态数一大堆,用 unordered_map

首先求出使得叶子达到深度 n 的最小点数 fn,不难发现递推式 f0=1,f1=2fi=fi2+fi1+1

同时求出使得叶子达到深度 n 的最大点数 gng0=1,gi=2i+12i21

那么我们的目标就是求出最大的 k 使得 n[fk,gk],则 k22 就是答案。

观察到满足 nfk 但是 n[fk,gk] 的只有 n=6 一种情况,先特判掉,剩下的就是高精度了,每次可以二分。

但是这题丧心病狂,卡空间。考虑使用压位高精,将问询离线排序从小到大找答案。

比较板子的题。

n 很小,考虑对于每行建立可持久化 trie 树,每次查询的时候一起往左儿子或者右儿子跳。

时间复杂度 O(nmlogm)

简单题。考虑每次插入进 trie 的时候,对于每个更新了的位置查看它当前值是否超过了历史最大值,如果有就用 vector 记录一下位置。

均摊复杂度显然是正确的。O(n|Σ|)

非常妙妙题。

发现这玩意儿是一个后缀数组排序的样子。考虑观察 sark 和这个串的变化的对应关系,可以推出 n+1 个形如 ais 中的后 n 个字符的首字母为 aj 的关系,一遍排序暴力跳就能找到原串了。

复杂度 O(nlogn)

子序列自动机板子题,把自动机建出来搞个 dp,反着跳一边就行了。

复杂度 O(nΣ)

首先考虑如何判断一个矩形 x[l,r],y[u,v] 是合法的,不难发现需要任意子矩形四个角的异或等于 0,进而推出每个 2×2 都要满足这个条件。

既然是 2×2,那就把原矩形压成一个 (n1)×(m1) 的矩形,每个小的 1×1 对应一个原矩形的 2×2。做悬线法求出最大全 1 子矩形,答案对 max(n,m) 取个最大值。

时间复杂度 O(nm)

良心 Ynoi,拜谢拜谢。

首先求一下全局的最大值,这个显然可以通过 Trie 搞定,复杂度 O(nlogw),假设其中一个最大值点对是 (x,y)

考虑哪些点是取不到 (x,y) 的:就是 x1y1 两条链上的点,所以只需要算一遍这些点就行了。从上到下 dfs,把其他子树加进去求一下最大值,复杂度还是 O(nlogw)

注意卡空间,要用 int

感觉很厉害。

首先想一个不带删的做法,考虑怎样的一个方案是合法的,根据 Hall 定理不难发现是任意一个子树中选的点个数不超过子树大小。

那就可以贪心了:从小到大加入,每次对于祖先一条链上的点,选出一个最小的替换掉,这个可以用树剖 + 线段树 + set 做到 O(nlog2n)

观察到每一个人员的出现时间是一个区间,所以最后只需要一个线段树分治来支持删除,时间复杂度 O(nlog3n)

好像可以全局平衡二叉树 / LCT 做到 O(nlog2n),不太会。

代码 4.3KB,写了 1.5h,调了 0.5h 无果,吃了个饭回来发现 Pushdown 写挂了,修了一下就过了,开心。

小 E 题/怄火。

考虑到状态数是 O(n3m3) 的,也就是 106 种,可以对于每个状态暴力转移。

现在问题就变成了一个有向图上状态走,得到胜负平局的结果。建出反图倒着推一遍就行了。

代码 3.45KB,细节很多,写了 1h,调了 20min,还卡常,最好用 int 而不是 ll

好像有拉插做法,不太会。

离散化一下,设 dpi,j 为考虑前 i 种划艇,其中第 i 种的个数在区间 [aj,bj] 内的方案数。

转移的时候考虑枚举上一个包含的区间 [ak,bk],假设有 cnt 个位置可以选择第 j 个区间,那么方案数为 (len+cntcnt),直接转移即可。

时间复杂度 O(n3)

暴力,记 (i,j) 为一只 doge 在 i,弹跳能力为 j 的状态,可能的状态数显然不超过 O((n+m)n),跑 bfs 最短路即可。

可能要用 bitset 判断状态是否存在,这样复杂度还带一个 O(n2ω)

大家好,我是不会 poly 也不会 GF 的小菜狗,于是我用纯组合意义做出了这道题。

考虑对于每棵树记录一个倒下的点,记为 pi,对于一个 p 计算对于答案的贡献。那么每次从 ii+1 转移的时候,需要考虑 pi+1pik+1 这个条件,除此之外,这个差 2k 就会有两种倒的方法,贡献乘上 2

我们把固定的 k+1 全部减掉,这样问题变为 nm(k+1) 个元素组成的序列分成 m+1 段区间(也就是选出 mpi),前 m 个区间中每出现一个长度 k1 的贡献就 ×2,求出所有方案的贡献之和。

考虑容斥,记 fi 为恰好 i 个区间 k 的方案数,gi 为钦定了 i 个区间 k 的方案数。g 是好算的,gi=(mi)(nm(k+1)ik+mm)

考虑套入二项式反演的式子并且加入 2mi 的贡献,可以得到答案就是 i=0m2mij=im(1)ji(ji)gj,化简得到 j=0m(mj)(nm(k+1)jk+mm)2mj(1)j,直接算就行了,复杂度 O(n)

白给题,这都能 2F?

首先排序,那么相当于选出 1i<j<kn 满足 gcd(ai,ak)=1。可以看到这个 gcdj 是无关的,所以当 i,k 固定的时候 jki1 种选法。

考虑计算 gcd(ai,ak)=d 的方案数,最后调和级数复杂度容斥一遍。对于每一个 d,找出所有 dai,现在需要计算两两的下标差减去 1,对于每个元素单独算贡献即可。

时间复杂度 O(nlogn)

太厉害,太厉害。

dpi,j 为长度为 i 的串操作到最后,右边剩下一段长度为 j 的都是 1 的方案数,那么要求的答案就是 dpn,n

考虑如何转移:对于 dpi,i,可以容斥计算:考虑到一个坏串一定是缩短之后 0 段更多,并且每个零段比旁边两个 1 段加起来长的,所以说对于所有 j<i12 都能对应上一种不合法情况,也就是 dpi,i=2i2j=1i12dpi,j

对于 dpi,j,中间一定存在一段 0,所以可以枚举这段 0 和右边那段 1 的长度,也就是 dpi,j=dpj,jk=j+2ij1p=1kj1dpijk,p

这个转移可以通过维护上三角前缀和,即 j+kidpj,k 来做到 O(1) 转移。

因此总时间复杂度为 O(n2)

首先拆位。

对于每个 and =1 或者 or =0 的要求,必须要整行整列都是 0/1,所以可以先搞定,如果有矛盾就无解。

接下来,考虑一个贪心,每次选出没填的个数最多的行或者列,任意选一个搞成符合条件的。

证明不想写,但是很好想。

每次把所有行列过一遍,需要 2n 次,操作次数是 2n,每次查询个数可以增量式处理,所以复杂度是 O(n2logV)

一款逆天问题。

思路很简单,考虑把这张图转成一个树的形式,然后 dp,记录当前的源点和汇点有没有被堵上。

细节......多的离谱,写了 3.46KB,吐了吐了。

最近怎么做了一堆大码量题和板题,是不是应该找点有技巧的题做做啊。

题意就是交换左右儿子,使得树变成完全二叉树。

首先叶子如果深度差大于 1 必定无解,否则可以贪心,只需要记录左右两个儿子有没有最大深度和最小深度。

时间复杂度 O(n)

断环成链,记录前面 5 个有没有出现喜欢或者就行了,复杂度 O(210n)

很久没有更新了,来点白给题。

直接求 b 不好求,但是观察到 k5,尝试扩展把所有的 bi,k 都求出来。

bi,k=j=1i(ij+1k)aj=j=1i((ijk)+(ijk1))aj=bi1,k+bi1,k1+[k=0]ai

做完了,复杂度 O(nk)

超级好题目!

首先有一个显然的 O(nlogX) 的做法:用动态开点线段树维护 0X 的所有答案,但是这是 ARC,显然不是让你写这个做法的!

我们考虑将 0X 的 A 中沙量作为 y=fi(t) 坐标化成图像,那么应该长成一堆斜率为 0,1,1 的分段折线。

观察这些折线的性质:首先有一个显然的性质是,对于任意 x,都有 f0(t)f1(t)fX(t)

其次我们可以发现,如果一条折线在某一个位置顶到了 f0 或者 fX,那么之后就会重合了。

我们维护 f0fX,如果有重合的情况,那么直接输出这个答案。否则,既然没有撞到边界,我们可以直接求和,因为每个位置的斜率都是 1,1

重合是好判的,对于所有的顶点判一下就行了。

给定的数组和问询是有序的,因此时间复杂度是线性的 O(n+m)

某种意义上来说是一个 product trick,组合意义还是很厉害的。

考虑到一个凸包的贡献是 2k,其中 k 是边上和内部的点数,那么从组合意义的角度来考虑就是 k 个点选或者不选的方案数。

因此我们要计数的就是满足包含一个子集组成了这些点的凸包的点集个数。

正难则反,考虑计数不合法的点集个数,这就是所有点共线的方案数,对于每条直线,减去 2cc 是直线上的点数。

可以枚举两个点确定一条直线,因此复杂度是 O(n3)

好像也可以优化到 O(n2logn),用 map 搞就行了。

首先对于操作分块。

对于之前块的修改可以直接做掉,对于当前块的修改从大到小排序,问询用可撤销并查集查询就行了。

复杂度根号 log,log 似乎在外面,也有可能是里面。

fimodk=i 时的最小数位和,是一个最短路的形式,仔细分析发现如果用 +1/×10 转移那么就是 01 最短路,复杂度 O(k)

k 为偶数就是 k2 带一堆 k

k 为奇数也好做的,类似于一个进制数,搞一下,就行了。

考虑二分答案,那么相当于判定按照 d 大到小排序之后的一个前缀得到 L 升果汁的最少代价是否 g

虽然 L,g 很大,但是观察到 l,p 都很小,因此考虑在值域上建立线段树,每个节点维护区间内最多选出几升,以及总的代价。每次查询的时候相当于在树上二分,如果左节点内的果汁已经够用那就进左子树,否则把左子树的所有代价都加上,进右子树。

要支持查询不同前缀,所以改用主席树,复杂度 O(nlog2n)

考虑一个数什么情况下必须被删:当 [l,r] 中没有除了他本身以外的约数。而当这些必须自己来删的数被删了以后,整个序列都被删了,因此其他数都是不必要删的。

每个关键的数都是独立的,并且相互是对称的,考虑计算出关键数的数量 x,那么问题转化为 n 个数中选出 x 个作为关键数,每个方案的最后一个关键数的下标之和,考虑到只有一个问询,可以暴力,枚举最后一个位置是哪个,组合数计算,时间复杂度 O(r)

模拟赛有个题的暴力是这玩意儿,但是我当时没做过这题,于是自己玩出来了,感觉很厉害!

考虑异或的性质:如果不断绕圈是会抵消的,所以我们把路径分为链和环两部分考虑。

任意 dfs 出一条 1n 的简单路径,在上面加入简单环,现在问题变为,有一个集合 S,从中选出若干个数,和 x 的异或和最大,这是线性基的经典应用,时间复杂度 O(nlogV)

太智慧了,真的想不出。

S 是最短的给定串,那么不难发现有用的串长度不超过 2|S|,所以看似无穷多的串已经被规定到了 n|S| 个长度为 2|S| 的串中。

尝试用线性基做数位 dp,数位 dp 就是固定一个前缀相等,然后算,这部分是 O(|S|2) 的。但是线性基暴力做是 O(n|S|3) 的,会 T。

接下来是人类智慧部分:考虑一种均摊的方式,每次消 1 都是 O(|S|) 的复杂度。我们观察到,如果插入一个 S,被消完之后得到了 T,那么 lsh(S)lsh(T) 在此之后就等价了。

因此我们可以发现,初始串和之后消出来的串总个数也是 O(|S|) 的,总的复杂度 O(n|S|2),可以通过。

还可以使用 bitset 优化,复杂度 O(n|S|2ω)

还是很人类智慧,真的想不出。

对于一个球 (x,y),要么被第 x 个 A 类波特扔进垃圾桶,要么被第 y 个 B 类波特扔进垃圾桶,因为波特和球的个数相同,所以必须一一对应。

考虑将这样的二元关系建图,形成基环树森林,如果不是基环树森林无解。

我们现在要求的就是对于每个连通块的一个定向方案求出拓扑序个数。

每个连通块最后都会变成一个内向树森林,而拓扑序个数就是 n!szu

但是考虑基环树有两种定向方式,所以把环反过来再跑一遍就行了。

时间复杂度 O(n)

太厉害。

首先瞎猜一个结论:只要每一层都是偶数个黑点那么后手必胜。

考虑达到这个条件的最少次数,如果每一层的黑点个数都求出来了,那么相当于相邻不同的 pair 个数,所以考虑建立虚树。

建虚树需要求 LCA,可以做到 O(1) 求出 LCA,O(1) 比较 dfn,然后在树上差分即可。复杂度 O(mlogV)

最小权闭合子图,没了。

区间按照右端点从小到大排序,设计一个 dp 方程: dpi 表示 i 区间结尾的最小不同位置个数。

可以预处理一个前缀和,方便 O(1) 计算区间修改后的代价。这个方程不难发现可以两棵线段树单点修改区间最小值维护,复杂度 O(nlogn)

首先 O(n) 做法不难想,不写了,但是这个玩意儿也不好优化,没有好的通项公式,也没有矩阵快速幂线性递推的形式......

这时候猛然发现输出一个浮点数,各种乱搞思路就突然出现了:观察到这玩意儿很快就会收敛,到 n 很大的时候基本没有变化了,因此我们把 n100min,过了。

如果早点看到这个题我可能就会 APIO T1 了,可惜没如果。

每一段的利润是独立的,可以分开算,现在相当于对于每个乘客求区间最大子段和,可以线段树维护,复杂度 O(qlogn)

我们设首项为 x,公比为 pq,那么我们需要保证 qn|x。这个事情看起来不好做,转化为枚举 p,q ,这样可行的 x 是一个区间,可以 O(1) 算个数。

分析一下枚举的时间复杂度:是 n 次根号 r2 的,考虑到当 n2 时这个值 r,可以直接枚举,而当 n=1 时答案就是 rl+1,于是做完了。

结论:答案至多为 2

1 可以特判,2 可以高斯消元,用 bitset 优化至 O(n3ω)

以前一直没太搞明白虚树的栈建法,这里记录一个非常简洁的建立方法。

将所有关键点按照 dfs 序排序,求出相邻点的 LCA,再次排序,对于相邻点 (ai1,ai),将他们的 LCA 作为 ai 的父亲。

正确性不证了。

建完虚树随便 dp 就行了。

太厉害了,神仙题。

按照位置顺序不好计数,考虑按照值域的顺序 dp。设 dpi,j,S 为值域 [1,i],已经选出 j 个数,目前 im 的有几个数出现了。

直接暴力转移就能过简单版,加强版考虑矩阵快速幂即可,复杂度 O(k38mlogn)

和 UM 单挑的时候他似乎被这题诈骗了,乐。

考虑预处理出每个节点到根的路径上最小值。观察到黑点只加不删,于是观察每个黑点和其他黑点形成路径的关系。我们强制设第一个黑点为根,这样每次加入一个点可以和根组成路径,对于子树内的点答案就都会跟这个值取 min 了。问询的时候,我们维护每次加入的黑点的到根的最小值的最小值,和这个点的最小值做比较就行了。

复杂度线性。

我们记每个栈里的 ai,0,bi,0,ai,1,bi,1Ai,Bi,Ci,Di

观察到 Ai+BiCi+Di 的情况是可以贪心处理的,先手必然会尽可能取大的。然而在 Ai+Bi<Ci+Di 的时候,先手取必然会吃亏。

考虑另一种分析:先手不一定非要取到最优的利益,他可以退而求其次。因此如果 Ai>DiBi>Ci 那也是赚的,否则一定双方都不会动,那就留着不动就行了。

复杂度 O(nlogn)

观察一条路径在 2×n 的网格中的形态:一定是左边一个圈,中间上下移动,右边一个圈的形态。

可以分开做 dp。

特判长度 2 的情况,他们不一定满足。

复杂度 O(n2)

Kummer 定理:(a+bb)p 因子最大幂次为 p 进制下 ab 的进位次数。

于是就可以数位 dp 了:设 dpi,j,0/1,0/1A 的从低到高前 i 位,一共进位 j 次,a+b 小于/等于 A,前一位有/没有进位的方案数。

复杂度 O(log2A)

UM 搬的人类智慧题,被初一学弟一小时秒杀了,我觉得很厉害。

观察到有用的串个数是 O(nΣ) 的。考虑对于这些串预处理出 SG 值。

直接记忆化搜索,记录所有前后缀信息,复杂度就是 O(nΣ2+qΣ) 的了。

首先考虑容斥:钦定集合 S 中的位置都是 1 的方案数,最后用一次 IFWT 求回答案。

钦定一个集合的方案数,我们考虑问题的实质就是图上选出 k 条不相交路径,大小分别为 a1ak 的方案数。可以考虑枚举拆分数之后 2n 计算,就可以通过了。

首先想一个转化:加入一个虚点 0,点权为 0,接下来对于点与点之间连边,边权为 ai+aj,并求出最大生成树,就是答案。

优化建图过程,考虑枚举子集,就能做到 O(3logV) 的复杂度,但是这还不够,考虑把这个过程像 FWT 一样操作,就能做到 O(VlogV)

UM duel 的时候爆杀我,太强大。

建出 Trie 树,这是显然的,接下来考虑怎么 dp。设 dpi,j,ki 子树中,j 是最浅的祖先,选了 k 个 Speed Dial 的最大节省时间,就可以做到 O(n3k)

我想的是记录子树内的状态,这样是不好做的,因为合并相邻子树的时候会爆炸。

考虑一定是尽可能选择长的循环节压,对于一个串,循环节就是 lennxtr,其中 nxt 就是 KMP 的 nxt

于是预处理所有后缀的 nxt,暴力 dp 就行了。复杂度 O(n2)

笨蛋主播小粉兔跟我 duel 这题只比我这个多项式彩笔快 20 分钟,乐的。

dpi,j 为第 i 组第 j 列的方案数,dpi,j=kdpi1,kp(ai1pk)(bi1pj)

后半部分利用 (nm)=(nnm) 变换之后,明显是一个范德蒙德卷积的形式,不难得到 fi,j=kfi1,k(ai1+bi1bi1+jk),是一个卷积形式,直接 NTT 即可。由于 |aibi|5,复杂度为 O(25n2logn)

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