做题记录

本文会有大约 \(3 \sim 5\) 天的时间偏移。

7/12

Link

「QOJ8341」序列

首先我想的是设 \(pre_i\) 表示将 \(1\sim i\) 排成有序的所需要的最小代价,\(suf_i\) 同理。

然后就 \(\text{WA}\) 了,就是你发现这种做法的本质在于用最大值将整个序列分成两段,但是两段之间的元素实际上是可以交换的,而且交换了可能使得答案更加优秀。

这样这种贪心就假了。

仍然从题目本身的性质入手,你去想,这道题最后要变成一个类似于单峰的形状,肯定是要分成两个部分的,那么我们就可以考虑决策每一个点 \(i\) 是放在最大值的左侧还是右侧。

对于点 \(i\) ,放在左侧的贡献是左侧的,与它产生的逆序对个数,因为无论你要不要把前面的,大于它的点放在右侧,你都会和它交换一次;同理,把 \(i\) 放在右侧的贡献是右侧和它产生的逆序对的个数,这样的贪心一定是可以的,而且两两决策独立,可以直接两边取 \(\min\) 再加起来。

时间复杂度是 \(O(n\log n)\)

「Apio2008」免费道路

这种 \(0/1\) 颜色染色,然后求有限制的最小生成树的题目可以使用 \(\text{WQS}\) 来做,但是这道题目没有边权,虽然可以随机赋权,但是还是太劣了。

首先肯定想到你要先填入一些 \(0\) 边,使得这些点至少能通过再加入若干 \(1\) 边,让整张图联通,然后剩下的 \(0\) 边和 \(1\) 边显然是可以任意替换的,我们就贪心填入 \(0\) 边,再用 \(1\) 边联通就行。

时间复杂度是 \(O(m\log m+n\alpha(n))\)

「QOJ6654」大纲

发现你一个点的值肯定是没有上限的,然后就考虑用类似于树形 \(\text{dp}\) 的思路去求这个下限,然后好像就做完了。

似乎是最水的一道题?

时间复杂度 \(O(n+m)\)

「QOJ975」Game

就是首先是经典的套路,设 \(E_i\) 表示在 \(i\) 这个位置的最大期望值,然后显然有 \(E_i = \max\{A_i,\frac{E_{i-1}+E_{i+1}}{2}\}\)

这个东西互相依赖,而且是取 \(\operatorname{max}\),根本无法去用高斯消元的类似物。

然后很 \(\text{Ad-hoc}\) 的一步就来了(我真的无法理解这是怎么想到的)。

就是发现 \(\frac{E_{i-1}+E_{i+1}}{2} \leq E_i\),这说明 \((i,E_i)\) 构成的图形是一个上凸包。然后就能把凸包建出来了。

答案 \(Ans = \frac{1}{n} \times \sum\limits_{i=1}^{n} E_i\),我们在构建凸包的时候顺带算一下和坐标轴围成的面积就行了。

时间复杂度 \(O(n)\)

「QOJ5954」Power Swapper

最有性质的一道题目。

首先一拿到题目,这是一个区间与区间交换的问题,很明显可以发现交换顺序不会影响最后的答案,最后的结果一定是一堆阶乘的和。

然后考虑从小到大选 \(k\),考虑当前层中的相邻两个数 \(i,i+1\),若两个满足 \(a_i +1 = a_{i+1}\),那么我们没有必要换,或者说,要换也是整体换,而若 \(a_i+1\not =a_{i+1}\),那么倘若现在不换,随着 \(k\) 越来越大,后面是没有机会再换了。

那么我们直接写一个 \(dfs\) ,然后在换的时候判断一下就行。

时间复杂度 \(O(n\log^2 n)\)

7/13

Link

A

首先考虑最暴力的想法,我们直接按照第一维排序,但是其它维度没有办法很好的处理,所以时间复杂度是 \(O(n^2k)\) 的。

考虑优化这个事情。其实我们可以维护 \(k\) 个指针表示每一维能走到哪里,然后边走边看能不能学习一个新的东西。

时间复杂度 \(O(nk)\)

B

个人觉得很板子。

就是首先发现我么可以对于每一个 \(i\) 记录一个 \(lst_i\) 表示这台机器上一次被使用的时间,暴力维护的时间复杂度是 \(O(nm)\) 的。

那么我们要优化这个事情,发现对于一次调用,我们的 \([l,r]\) 这段区间里面的 \(lst_i\) 会变成一个类似于等差数列的东西。

这个东西本质上就是维护一个极长的,\(lst_i\) 构成等差数列的连续段,使用 \(\text{ODT}\) 即可。

时间复杂度 \(O(m\log n)\)

C

首先考虑如何刻画这个从 \(1 \rightarrow n\) 的过程,我们发现,它一定是形如:原地上升,然后走一步并且上升;不上升也不下降;原地下降,然后走一步并下降。

这样我们就可以通过枚举(或者二分、三分)最高点来求答案了。

感觉上没有什么优化空间了,这个时候我们就应该重新寻找性质。

显然我们可以减少不上升也不下降的段的长度。(我们可以在最左右两边的一条边上升、下降使得段的长度减少 \(2\)

最后我们的段的长度会变成 \(0\) 或者 \(1\),我们直接预处理前缀的最小值和后缀的最小值就行。

时间复杂度 \(O(m\log n)\)

D

场切数据结构题目。

首先这个感觉就非常的扫描线,我们考虑按照右端点排序,去考虑左端点。

我们可以对于每一个 \(i\),设置一个 \(mx_i\) 表示,覆盖到 \(i\) 的线段的左端点的最大值。

一段区间合法当且仅当 \(\min\limits_{i=l}^r(mx_i) \ge l\) ,直接使用吉司机维护就行。

时间复杂度 \(O(n\log n)\)

7/13 ~ 7/14

Link

「QOJ8639」消除

考虑自动机。

我们首先发现你的状态长度一定 \(\leq 2\) ,否则你肯定会去消除。

考虑这些状态:\(\emptyset,1,0,01,11,10\),分别去推一下转移就行。

「QOJ6522」Digit Mode

发现如果不去对众数做约束那么时间复杂度(或者说叫状态数)肯定会爆炸,那么我们考虑去枚举 \(target\) 做为众数,且众数的出现次数为 \(cnt\)

有了这个有什么用呢?我们可以对于这个东西做 \(dp\)(无约束情况下)。但是显然我们是有上界限制的。

我们完全可以枚举我们踩中了 \(1\sim i\) 位的限制,且 \(i+1\) 位我们填了 \(j\),然后就能转化为无约束 \(dp\) 了。

「QOJ5948」Trie Sharding

非常牛的题目,让我用背包草过去了。

首先有一步很显然的转化:你会让公共部分尽可能的少,所以考虑算出公共部分的和的最小值。

我们现在考虑设 \(dp_{i,j}\) 表示在 \(i\) 这个点,目前有 \(j\) 个颜色的最小公共长度。

\(ndp_{i,j+k-l}\leftarrow dp_{i,j} + dp_{son,k}\),然后在转移时统计一下方案数就行。

「QOJ5052」Rectangle Flip 2

最开始的考虑是,我们去找到某一个被挖掉的点的四周有哪些点挡着矩阵进行扩展,类似于悬线?

较为简单的考虑是我们枚举行的左端点和右端点,然后去滑动窗口(类似物)枚举我们的列。

将每一个格子被干掉的时间打在格子上,显然贡献为一个矩阵中的最小值,直接搞一个差分维护答案就行。

「QOJ10756」Games on the Ads 2: Painting

首先一眼会想到建边,我们将 \(i \rightarrow j\) 表示 \(i\) 号刷子要在 \(j\) 号刷子之前使用。

显然这个东西是一个完全二分图,但是这里面的限制有一部分是无向的(就是行和列都能先使用),那怎么做呢?

由于 \(n\) 极度小,我们用 \(2^n\) 时间来枚举这些边的方向。

剩下的问题就行对这个图的拓扑序进行计数了。

有一个显然的事情就是入度为 \(0\) 的点只会全部出现在左部或者右部,那么我们对于一层上的所有点,这些点必须被连续地删除,那么 \(cnt_i\) 表示 \(i\) 层中的点的个数。

则答案为:

\[Ans=\prod_{i=1}^{maxlayer} cnt_i! \]

「QOJ431」Mysterious Array

首先肯定会去想从 \(1\)\(n\) 填数,或者从 \(n\)\(1\) 填数,但是发现我们差了一点东西。

这个东西就是每一步我们能填的位置,这个东西看起来是不好去计算的。

我们可以根据限制 \(\{[l,r],val\}\),得出我们 \([l,r]\) 的区间内填的数必须 \(\ge val\),且必须存在一个 \(i\in [l,r], a_i = val\)

这个东西是可以预处理的,我们设 \(limit_i\) 表示 \(i\) 这个点最小能填什么数。

然后就十分简单了,我们从 \(1\)\(n\) 填数字,然后找到对应的约束,将方案数乘起来就行。

「QOJ11495」Brackets & 「BZOJ2981 Poi2002」括号

第1部分

我们先看一下前者的做法。

考虑使用类似于 笛卡尔树 构建的方法:我们可以每一次加入一条新的点,然后你可以把它接在任意一个点的左子树上,可以将栈中的一部分元素放在当前点的左子树上,然后你发现这些操作不会改变其它点的符号,所以一个点的符号仅和其入栈时的奇偶性有关。

考虑设 \(dp_{i,j}\) 表示当你走到 \(i\) 号节点的时候目前算上 \(i\) 号点栈中还有 \(j\) 个元素的方案数。

考虑转移:

\[dp_{i,j} = \sum\limits_{k=j-1}^{i-1} dp_{i-1,k} \]

注意这里的 \(j\) 的奇偶性和当前的符号有关。当目前符号为负号的时候,\(j\) 必须为奇数,否则必须为偶数。

然后这样时间复杂度为 \(O(N^3)\),前缀和优化做到 \(O(N^2)\)

第2部分

考虑 后者 怎么做?

我们发现我们现在的瓶颈在于奇偶性的刻画不是很好。而且我们发现当前这个点的奇偶性和前置的奇偶性我们其实是已知的。

我们再来详细刻画一下这个条件,当 \(i\)\(i+1\) 的奇偶性不同的时候,从 \((i,j)\) 可以走到 \((i+1,j+1),(i+1,j-1),(i+1,j-3)\dots\),反之,你能走到 \((i+1,j),(i+1,j-2),(i+1,j-4)\dots\)

这样还是太难看了,我们考虑将每一次奇偶性变化的时候,都把网格向左移动,这样我们就统一了我们在网格上的走法。

那么这样看起来还是不能做,网格的大小是 \(10^6 \times 10 ^ 6\) 的,带有这么多限制的格路计数显然无法通过。

观察题面发现,保证答案小于 \(10^9\),这暗示我们什么呢?

我们考虑一次网格的左移,我们要么会直接向上走,要门会走向左边的点,可以很好的知道,这个答案一次至少是会乘 \(2\) 的。

那么我们的网格平移次数就是 \(O(\log Ans)\) 级别的,也就是网格实际宽度约为 \(O(\log Ans)\)

那么我们现在如何计算答案呢?可以考虑暴力在行间 \(\text{dp}\),时间复杂度约为 \(O(N\log N + \log^3 Ans)\),优化处理组合数的过程可以做到 \(O(N+ \log^3 Ans)\)

7/16

Link

A

首先考虑贪心,考虑从 \(n\) 开始向 \(1\) 填我们的数,那么我们当前填的数 \(i\) 一定是一条从叶子开始的链,显然我们应该选择最长的链来填当前的数。

然后这里我使用的是用 \(\text{dfs}\) 序和线段树来维护每一个叶子可能向上的最长链的长度。对于一次修改我们直接暴力的跳就行。

考场上犯唐了,当时没有处理到 \(n=1\),还有就是没有开 \(\text{long long}\) 导致了 \(\text{WA}\)

B

首先是很显然的转化,就是子区间和不为 \(0\) 等价于前缀和不重。

我们考虑将前缀和放在数轴上考虑,那么我们的 \(-1,1,-2,2\) 等价于在数轴上左右跳。不妨假设 \(target=-2A-B+C+2D > 0\)

那么我们肯定会呈现这样一种局面:先在起点附近跳跃,然后整体趋势向右,最后经过调整落到 \(target\) 这个点上。

我们先来考虑中间部分,不难发现,中间部分只会有 \(+2,+1,(+2)+(-1)+(+2)\) 三种,这看起来非常简单。

现在我们需要考虑起始部分和终止部分怎么跳。根据手玩发现只有:\(k(-2)+(-1)+(k+1)(+2),k(-2)+(+1)+k(+2),\emptyset\) 三种,其实终止也是一样,那么加起来就是 \(9\) 种情况,枚举一下,用组合数乘起来就行。

C

赛时犯唐了,暴力都没写对。

首先,因为每一个棋子的路径独立,所以考虑预处理 \(SG\) 函数然后 \(O(1)\) 求出答案。

首先,我们设 \(dp_{i,j,k}\) 表示 \(i\) 行,目前在 \(j\),我们是从 \((i-1,k)\) 向下走走到的 \(i\) 行。这个显然是对于 \(i\) 行全为空才非常的有用,如果有障碍格子,我们完全可以将 \(k\) 变为 \(0,1,2\) 表示刚到,向左,向右。

那么我们现在的目标就是优化一行全为空的时候的 \(SG\) 转移了。这里有一个小性质就是 \(SG(i,j)\leq 2\)

考虑这样的一条路径:\((i+1,j+1) \rightarrow(i,j+1) \rightarrow (i,m) \rightarrow (i,1) \rightarrow (i,j)\),这个应该是转移的一个过程(假定我们要求的是 \(SG(i,j)\),列数均在模 \(m\) 意义下)。如何优化呢?我们目前已知的是 \(i+1\) 行及以后的所有的 \(SG\) 的值,那么如果我们搞出来一个 \(to[i][j][k]\) 表示 \((i,j)\) 这个点的 \(SG\) 值为 \(k\) 时,\(SG(i,m)\) 的值是多少,同理我们设 \(arr[i][j][k]\) 表示 \(SG(i,m)\) 的值为 \(k\) 的时候 \(SG(i,j)\) 的值是多少。这样我们就能优化掉 \(SG\) 函数的转移了。

D

首先有朴素 \(dp\):设 \(dp_{i,j}\)\(b_i=j\) 的时候的最小代价。然后有个很显然的结论是 \(j\) 只能取到 \(a\) 这个序列内的数,因为这样取一定不劣。

现在我们设 \(dp_{i,j}\) 表示 \(b_i\)\(a\) 中从大到小第 \(j\) 个的时候的最小代价。那么我们有转移 \(dp_{i,j}=\min\limits_{k=1}^{j} \{dp_{i-1,k}\}+f(val_j,a_i)\)

那么我们的操作就是一个类似于取前缀最小值,然后再进行两段区间修改的类似物,这个东西好像可以把第二维拍到线段树上去做。

我们现在设 \(a_{i}\) 是从大到小的第 \(rnk\) 个,那么我们先考虑 \(f\) 函数对整体的贡献:\(\forall j \in [rnk+1,n],f(val_j,a_i)=C\),而 \(\forall j \in [1,rnk-1],f(val_j,a_i)=val_j-a_i\)

这个东西看上去就很难维护,再加上我们还有取前缀最小值的操作,似乎这个做法就倒闭了。

实则不然,考虑到我们已经将 \(i-1\) 层做过前缀最小值操作了,那么我们现在的东西应该是单调不增的,对于我们的加法操作:对于区间加 \(C\),不影响单调性,对于区间加 \(val_j-a_i\),由于 \(val_j\) 单调递减,所以加完后我们的值也单调不增。

现在的问题在于怎么做这个前缀最小值的操作?发现你加法操作完了过后,序列会长成两端单调不减的段,你直接用第一段的末尾去抹平第二段就行,做个线段树上二分。

然后整个题目就做完了。

7/17

Link

「QOJ335」Vari-directional Streets

非常牛逼的题目。

这个东西首先可以把 \(\text{SCC}\) 缩成一个点,剩下的图就是一个 \(\text{DAG}\),考虑拓扑类似物。

发现我们一个点要能到所有的点,它必须是所有前驱的唯一汇点,是所有后继的唯一源点(就是说必须要是一层当中的唯一一个)。

但是又一些特殊情况你需要考虑。当你目前正在考虑第 \(i\) 层时,不能出现 \(1\sim i-1\) 的某一个点的所有出边全部指向 \(i+1\sim n\) 层中的点,这个东西可以在拓扑序记录的时候同步计算。

然后正着一边拓扑,反着一遍拓扑就行。

「QOJ3867」Antennas

看到绝对值,肯定首先就是要把这个东西给拆开。

拆开后就是:\(\forall j\in[i+1,n],j\in[i+1,i+p_i] \and i\in [j-1,j-p_j]\)\(\forall j \in [1,i-1],j\in[i-p_i,i-1]\and i\in [j+1,j+p_j]\)

然后我们可以对于每一个 \(i\),维护 \(i+p_i\)\(i-p_i\) 的值。

\(\text{BFS}\) 的过程中,我们考虑当前点 \(u\) 能走到哪里?其实能走到的是满足上面的限制的点。

然后我们可以维护一个类似于势能线段树的东西,去暴力地找合法的下一个点。

每一个点只会被找到 \(1\) 次,所以时间复杂度正确。

「QOJ6523」Escape Plan

看上去是一个类最短路问题。

考虑到每一个点有一个 \(d_i\),那么我们的答案一定为所有到达 \(i\) 点的路径长度的第 \(d_i+1\) 小的。然后当我们成功了一次到达后,我们就能更新后续点的答案了。

然后就水完了。

「QOJ1206」IOIOI Cards

\(Val_i=a_i\oplus a_{i-1}\),则最终我们要求 \(Val_i\)\(0\)

考虑一次翻转,我们只会改变 \(Val_l\)\(Val_{r+1}\)。转化就做完了,最后跑一个最短路就行。

「QOJ6681」Triangle City

好题目。

就是你发现我们考虑哪些边要被删掉是较为简单的。那么最后我们一定要形成一个从 \((1,1)\)\((n,n)\) 的,每条边只能走一次的路径,这显然是一个欧拉路径。

考虑到我们现在所有点的度数都是偶数,我们要求 \((1,1)\)\((n,n)\) 的度数要是奇数,我们就必须要删掉一条边,那么又有一个点的度变成奇数了,我们仍然需要删除这个东西的另外一条边。

很明显,我们最后删除的,是一条从 \((1,1)\)\((n,n)\) 的最短路。

把最短路的方案求出来 ,再跑欧拉路就能得到答案了。

「QOJ10708」Decent Path Around Bajtów

首先肯定会把由无向边连起来的点全部当成一个点来处理,这样剩下来的一定是一个 \(\text{DAG}\),而我们无向边连成的块一定是一棵树。

这个非常的有性质啊,我们可以对于树上的每一个节点 \(u\),记录一个 \(fst_u\) 表示第一次到达这个点的时刻,这个东西的转移等价于你要做一个换根 \(\text{dp}\),然后转移即可。

posted @ 2026-07-16 22:08  To_string  阅读(10)  评论(0)    收藏  举报