Solution Set #11

177 qoj7607. The Doubling Game 2

首先可以发现对于一个局面,操作到这个局面的方案是唯一的(考虑一条边左右的棋子数量,可以知道这条边的移动方向,删去所有不移动的边之后,每个联通块只有一个点有棋子,而对于只有根有棋子的局面构造显然唯一)

据此可以 \(\mathcal{O}(n^2)\) DP:设 \(f_{u,i}\) 表示 \(u\) 往上传一个大小为 \(2^i\) 的子树的方案,\(g_{u,i}\) 表示父亲往下传大小为 \(2^i\) 的子树的方案,\(h_u\) 表示父亲边断开的方案。以 \(f\) 的转移为例子,子树中需要出现大小为 \(2^{0\sim i-1}\) 的子树,状压扫过去即可。其余情况不难转移。

考虑优化。这类问题的 DP 优化通常考虑把转移数压到每个点的轻子树大小。此题有如下构造:把子树从大到小排序,那么在转移一个点前,状态的范围是它前面子树大小的 \(\max\)。对于重子树,它贡献上来的子树至多是前面子树的两倍,所以状态数可以做到与轻子树大小同阶,加上转移的复杂度,可以做到 \(\mathcal{O}(n\log^2 n)\)

https://qoj.ac/submission/331806

178 qoj1197. Draw in Straight Lines

设置变量 \(bh_{i,j},bv_{i,j},wh_{i,j},wv_{i,j}\),分别表示 \((i,j)\) 被水平染黑,竖直染黑,水平染白,竖直染白。可以按照如下方式刻画贡献:

  • 水平方向的黑色贡献:\(a\sum bh_{i,j}+b\sum bh_{i,j}\overline{bh_{i,j+1}}\),其余情况对称。
  • 修正黑色格子的贡献:\(c\cdot \overline{bh_{i,j}}\overline{bv_{i,j}}+\inf\cdot (wh_{i,j}+wv_{i,j})\)
  • 修正白色格子的贡献:\(c\cdot (bh_{i,j}\overline{wv_{i,j}}+bv_{i,j}\overline{wh_{i,j}})+\inf\cdot bh_{i,j}bv_{i,j}\)

贡献形式可以用最小割刻画。

Submission #329003 - QOJ.ac

179 2024.2.19 考试 T3(部分分)

题目大意

先考虑 \(S=1\) 怎么做。在到达第一个 \(a_i=2\) 的点之前,步数一定是从某个点出发往回绕若干圈再走回来,此时前缀所有点的状态不变。到达之后是类似的,从一个点开始往回跳,转一圈之后跳到这个点后面之后,除了 \(a_{i-1}=2\) 的点之外,其它点的状态都不会变。

然后 \(S>1\) 的情况是一样的,状压所有 \(a_{i-1}=2\) 的点即可。

180 qoj7106. Infinite Parenthesis Sequence

考虑另一个问题:设 \(f(i,j)\) 表示 \(i\) 轮第 \(j\) 个括号的位置。求出这个之后就可以套一个二分求出答案。

分情况讨论这个东西的转移:

  • \(f(i+1,j)=f(i,j)+1\),如果这个括号后面是一个右括号。
  • \(f(i+1,j)=f(i,j+1)\),如果这个括号后面是一个左括号。

写成较为数学的形式就是 \(f(i+1,j)=\min(f(i,j)+1,f(i,j+1))\)。稍微化简一下可以得到:

\[f(k,i)=\min_{i\leq j\leq i+k}(f(0,j)+k+2(i-j)) \]

\(F(j)=f_j-2j\),注意到 \(F(j+m)=F(j)+n\),可以拿这个缩小 \(j\) 的值域。对于 \(k\) 小的时候,直接令 \(i\gets i\bmod m\)。对于 \(k\) 大的时候,可以发现只有长度为 \(m\) 的区间有用,规约到上面的情况。那么拿 st 表做 RMQ 即可。

Submission #332229 - QOJ.ac

181 qoj8179. 2D Parentheses

考虑贪心。所有点按照 \(x\) 从大到小排序之后匹配,有结论:我们只会匹配可以匹配的结点中 \(y\) 最小的,证明考虑如果有 \(y\) 更小的点,那么匹配之后这个点要么在矩形内部,要么被挡住了,一定不能得到合法方案。

所以只需要判断这个唯一的匹配方式是否满足条件。矩形包含或不交可以转化成矩形的边界没有交点,扫描线+set 维护即可。

Submission #333185 - QOJ.ac

182 qoj8213. Graffiti

考虑 ABC 串的做法,其它做法是类似的。直接 DP 是三方的。考虑一个构造:黑白染色,将所有白色都染上 B,剩下的黑色部分存在染色方案,使得对于每个 B,其相邻的结点总有一半是 A,一半是 C,这取到了答案的上界。所以 DP 的时候只需要记录相邻的点中 A/C 的点的数量即可。注意到 DP 是凸的,所以维护差分数组就可以了,复杂度 \(\mathcal{O}(n\log n)\)

Submission #333323 - QOJ.ac

183 loj4087. 「USACO 2024.1 Platinum」Merging Cells

可以想象两个数之间有一个隔板,操作相当于随机一个删除隔板的顺序。

容易想到 \(\mathcal{O}(n^3)\) 的区间 DP:枚举最后的数,转移的时候前缀和优化。

注意到 DP 起点唯一而终点不同,可以设计出新的状态:\(f_{l,r}\) 表示已经拥有区间 \([l,r]\) 的前提下,获胜的概率是多少。差分优化转移,可以做到平方。

提交记录 #2009150 - LibreOJ (loj.ac)

上面几个题都好笨蛋啊。

184 2024.2.20 模拟赛 T2 count

题目大意

枚举前缀最小值的值 \(m\) 和位置 \(i\),那么 \(A\) 合法的条件相当于 \(i\leq A_1\leq A_2\leq \cdots\leq A_k\),且 \(1\sim m-1\) 都在 \(A_k\) 之后。

\(1\sim m-1\) 的位置为 \(A_{k+1\sim k+m-2}\),那么可以插板计算序列 \(A\) 的数量,复杂度 \(\mathcal{O}(nx)\)

然后随便推推式子就可以了。

185 loj3818. 「CEOI2022」Parking

建图,底下的颜色向上面的颜色连边。按照联通块的形态决定优先还原哪些联通块,具体地:

  • 一条链,链的一端点没有出边。可以直接解决链的端点,然后删去。
  • 一条链,链的两端点都有出边。找到其中一个端点,顺着出边一直走直到没有出边。此时当前两个点都在顶端,将两个点放在同一个空位置上,然后把原链拆成两条链。
  • 一个环,按照没有出边的点的个数从小到达排序还原。选择环上其中一个有入边的点,将其中一个点放进空位置,拆成一条链。

容易发现操作次数的一个下界是没有匹配的车的数量加上两个车都在顶端的车的数量,而上述构造达到了上界,所以是最优的。

提交记录 #2009413 - LibreOJ (loj.ac)

186 loj3482. 「USACO 2021.2 Platinum」Minimizing Edges

转化一下问题:假设 \((x_i,y_i)\) 分别是点 \(i\) 的最短路和奇偶性不同的最短路,那么需要满足两个条件的其中之一:

  • \(i\)\((x_j-1,y_j-1)\) 有连边。
  • \(i\)\((x_j-1,y_j+1)\)\((x_j+1,y_j-1)\) 有连边。

把所有点按照 \(x+y\) 为第一关键字,\(x\) 为第二关键字排序,贪心:

  • 如果 \((x+1,y-1)\) 存在:
    • 优先把前面的边补上一条后面的边使得第二种情况达成。
    • 如果 \((x-1,y-1)\) 存在,将剩下的点达成第一种情况;否则,达成第二种情况。
  • 如果不存在:全连 \((x-1,y-1)\)

需要注意的细节:

  • \(x=0\) 时不需要往前面连边。
  • \(x+1=y\) 时,往后的点就是它本身,所以一条向后的边可以贡献到两个点上。

提交记录 #2009647 - LibreOJ (loj.ac)

187 qoj151. Nice Lines / 【PR 1】直线

考虑在 \(x=10^5\) 这条直线上询问,注意到询问的答案关于 \(y\) 构成分段一次函数,断点即为直线和 \(x=10^5\) 的交点,即 \((x,a_ix+b_i)\)。如果 \(x\) 远大于 \(b_i\),那么可以直接用 \(\lfloor\frac{a_ix+b_i}{x}\rfloor\) 来得到 \(a_i\),进而得到直线。所以我们的目标是求出所有直线与 \(x=10^5\) 的交点。

一个做法是分治,假设我们要求 \([2x,2y)\) 范围内的所有交点,如果 \(f(2x)+f(2y)=f(x+y)\),说明 \(2x\)\(2y\) 在一条直线上,即 \([2x,2y)\) 间没有交点,直接退出,否则分治 \([2x,x+y),[x+y,2y)\)。这样做是 \(\mathcal{O}(n\log V)\) 的。

尝试令每次分治的区间内都有至少一个点。将序列分成若干块,第 \(i\) 块为 \([(i-1)x,ix)\)。此时 \([(i-1)x+10^4,ix-10^4)\) 中间是没有点的,可以求出其直线对应的解析式。那么我们维护分治边界两块的直线,如果两个直线的交点在分段函数上,说明中间只有一个交点,加入答案并推出分治。否则,以交点坐标为分界点分治两边。操作次数的分析和线段树结点个数类似,反正是线性。

Submission #334265 - QOJ.ac 但是基本是抄的 hos_lyric 代码(

188 loj3464. 「WC2021」斐波那契

\(F_n=af_{n-1}+bf_n\),其中 \(f_n\) 为斐波那契数列第 \(n\) 项。

需要解:

\[af_{n-1}\equiv bf_n\pmod m \]

如果 \(m\) 是质数则可以直接除过去。所以需要想办法让 \(f_n\)\(b\)\(m\) 互质。

\(g=\gcd(a,b,m)\),并令 \(a,b,m\) 同时除 \(g\) 得到 \(a_1,b_1,m_1\)。先考虑把 \(b'\) 除过去。由于 \(\gcd(b_1,m_1)\)\(a\) 互质,所以 \(\gcd(b_1,m_1)|f_{n-1}\)。令 \(d_1=\gcd(b_1,m_1)\),同时除:

\[a_1\frac{f_{n-1}}{d_1}\equiv \frac{b_1}{d_1} f_n\pmod {\frac{m_1}{d_1}} \]

设除之后是 \(b_2,m_2\)。有:

\[a_1\frac{f_{n-1}}{d_1}b_2^{-1}\equiv f_n\pmod {m_2} \]

接下来考虑除掉 \(f_{n-1}\),同样注意到 \(\gcd(f_n,f_{n-1})=1\),所以 \(\gcd(m_2,\frac{f_{n-1}}{d_1})\) 只能等于 \(1\),换句话来说 \(\gcd(m_1,f_{n-1})=d_1\),这样就可以直接除过去了。

所以我们把 \((d_1,f_n,(\frac{f_{n-1}}{d_1})^{-1})\) 丢到 \(g\) 上面,查询的时候只要得到 \(g,d_1,a_1b_2^{-1}\) 然后直接查询即可。

大概是在预处理的时候枚举和 \(a,b\) 有关的变量简化条件来方便查询,可能做数学题的时候比较有用?

提交记录 #2010611 - LibreOJ (loj.ac)

189 【PR 1】守卫

首先可以发现,只有 MST 上的边是有用的。

考虑费用流,建立如下模型:

  • 每个边向它的两个点连边,表示给边定向,即指定生成树上一个点为另一个点父亲。
  • 每个守卫的集合向它连边,表示指定为根。

直接跑费用流即可。

注意守卫不能重合。

Submission #334215 - Public Judge (pjudge.ac)

190 qoj5423. Perfect Matching

相当于找到一个图的线图的完美匹配。

考虑如下构造:建立 DFS 树,自下而上构造,每次加入一个点除了其父亲边的所有边。如果边的数量为奇数,则把父亲边也加入,并在之后的构造中删除这条边。

这样可以构造出所有联通块边数为偶数的情况,若不能构造显然无解。

Submission #334604 - QOJ.ac

191 qoj6308. Magic

转化一下题意:有 \(2n\) 个隔板,每次可以在 \(l_i,r_i\) 的位置插一个隔板,并把中间的隔板全部消掉,最大化隔板数量。

有个有意思的三方区间 DP 做法:枚举第一个贡献到答案的隔板,那么跨过这个隔板的区间都会被删掉,这样就可以分成两个子问题。

推一下结论:\(l_i<l_j<r_i<r_j\),那么 \(l_j\)\(r_i\) 不能同时是隔板。

猜测这是最后隔板集合合法的必要条件,构造证明:每次取出所有不被其它区间包含的区间,取最左边或者最右边的隔板,这个隔板不会被任何区间限制。那么操作这个区间,然后继续做。

现在需要高效求一个二分图最大独立集问题。使用 bitset 优化匈牙利,复杂度 \(\mathcal{O}(\frac{n^3}{w})\)

qoj.ac/submission/334680

192 loj3490. 「JOISC 2021 Day2」逃跑路线

问题的关键在于求出一天以内 \((u,v)\) 间的最短路。

可以发现 \(dis_{u,v}(T)\) 是一个递增的分段函数,可以证明段数不超过 \(m\),进一步地,对于任意不同的 \(T\),以 \(u\) 为源点的单源最短路之多有 \(\mathcal{O}(m)\) 种情况(考虑增加时间,必定有一条边顶到上界,此时把这条边删去不影响答案,最多只会删去 \(m\) 条边)

一种算法是利用 187 的做法分治寻找断点,需要做 \(\mathcal{O}(m\log V)\) 次单源最短路,单次复杂度为 \(\mathcal{O}(n^2)\),需要对 \(n\) 个点求。视 \(m=\mathcal{O}(n^2)\),复杂度为 \(\mathcal{O}(n^5\log V)\)

可以发现 \(\log\) 因子其实可以去掉。我们求出一个局面之后,容易 DP 求出这个局面的最大 \(T\),可以递推到下一个局面,复杂度 \(\mathcal{O}(n^5)\)

以所有 \(u\) 都作为源点跑 Dijkstra 是浪费的,考虑直接枚举瓶颈边,钦定到达瓶颈边的时间顶到上界,求出 \(f_{id,u},g_{id,v}\) 表示边 \(id\) 往前找到 \(u\) 的最短路和往后找到 \(v\) 的最短路。维护 \(A_{u,v}\) 表示 \(u,v\) 间最短路。对于一组询问,我们找到 \(C_{id}-L_{id}-f_{id,u}\geq T\) 的所有 \((u,id)\) 二元组,利用 \(f_{id,u}+L_{id}+g_{id,v}\) 更新 \(A_{u,v}\) 即可,可以离线后双指针维护,复杂度 \(\mathcal{O}(n^4)\)

提交记录 #2011625 - LibreOJ (loj.ac)

193 MO 题

MO 老哥给的有趣构造题,但是他没有告诉我们答案。我们机房给出了 \(k=16\) 的构造,不知道能否更优。欢迎各位同学分享你的构造(

upd:好像答案是 \(15\) 啊,有没有老哥教教/kel

构造如下:

  • \(11\) 个集合 \(S_{0\sim 10}\)\(S_i\) 为全体二进制第 \(i\) 位为 \(1\) 的数的集合。
  • \(12\) 个集合 \(S_{11}\),表示全体 \(2|\text{popcount}(x)\) 的数的集合。
  • \(13\sim 16\) 个集合 \(T_{0\sim 3}\),令 \(A_i\) 表示 \(0\sim 11\) 中二进制第 \(i\)\(1\) 的数构成的集合,则 \(T_i=\{num|\sum_{x\in A_i}[num\in S_x]\equiv 1\pmod 2\}\)

解释一下,前 \(12\) 个集合在没有说谎的情况下可以给出答案,否则给出前 \(12\) 个集合存在集合说谎。原理是在说谎的情况下,前 \(11\) 个集合给出的数的二进制位和答案的二进制位恰有一位不同,奇偶性改变,所以若前 \(11\) 个集合给出的数不满足第 \(12\) 个集合则表明说谎,否则给出答案。

\(4\) 个集合在说谎的情况下给出了哪个集合说谎。容易发现 \(T_i\) 给出了答案在 \(A_i\) 集合的二进制位里 \(1\) 的个数的奇偶性,如果这个答案和前 \(11\) 个集合给出的答案不符,则说明说谎的集合编号在 \(A_i\) 中,如此可以确定说谎的集合。

194 qoj8240. Card Game

一个方便的求单组询问的方法是:定义 \(nxt_i\) 表示 \(i\) 的后一个与 \(i\) 颜色相同的位置,若 \(nxt_l\leq r\),则 \([l,nxt_l]\) 必然全部被删去,所以我们可以令 \(l=nxt_l+1\) 继续做。否则 \(l\) 一定在答案中,令答案加一,\(l=l+1\),然后继续做。

分块已经可以做到 \(\mathcal{O}(n\sqrt{n})\) 的复杂度,甚至可以带修。考虑利用主席树做到 polylog。假设第 \(l\) 棵线段树维护了所有 \(r\geq l\) 的答案,那么 \(l\) 是由 \(l+1\) 的前半段区间和 \(nxt_l+1\) 的后半段区间拼接得到。遍历区间定位,然后用结点复制实现可持久化即可。

https://qoj.ac/submission/336017

195 uoj839. 龙门题字

首先把初始的 \(a\) 也看成一个操作。

考虑所有满足 \(l_i=1\) 的操作,找到 \(x_{i,1}\) 最大的操作中 \(r_i\) 最小的操作 \(p\),对所有操作进行如下修改:

  • 如果 \(r_i\leq r_p\),那么把 \(i\) 删去。
  • 否则,将 \(x_{i}\) 的前缀替换成 \(x_p\),称其为将 \(i\) 染色。

这样所有 \(l_i=1\)\(x_{i,1}\) 都相同,于是我们可以把第一位删去,进入新的子问题。容易证明原问题中首位最大的所有方案都可以对应到新问题上的一个方案。

直接暴力模拟可以得到一个 \(\mathcal{O}(L^2)\) 的做法,考虑优化。注意到如果某个操作的首位是之前被染过色的,那么它一定不会成为上文中的操作 \(p\),因为将它染色的操作一定比它更优。所以首位被染过色的操作一定不会成为答案,自然地,其首位的具体值也不重要,我们只需要维护一个操作被染色部分的右端点 \(col_i\)。考虑 \(col_i\) 什么时候变化,注意到若 \(r_p>col_i\) 的时候,操作 \(i\) 一定被染色,所以每次将 \(col_i\)\(r_p\)\(\max\) 即可。

https://uoj.ac/submission/679817

196 uoj840 龙门考古

因为想题的时候很混乱所以下面比较意识流。

考虑怎么根据残缺的 \(a\) 求出 \(b\)。先填前缀最大值部分,剩余的部分显然是递增填。考虑前缀最大值需要满足的条件,首先它需要比 \(nxt_{i}-1\) 之前的所有数都要大,其中 \(nxt_i\) 为下一个前缀最大值位置。其次,它需要比非前缀最大值的递增部分的在 \(nxt_i-1\) 之前的最大值要大。

在值域上 DP,设 \(f_{i,j}\) 表示值域为 \(i\) 而递增填部分最大值为 \(j\) 的方案数。填非前缀最大值的方式是简单的,只需要考虑它是否已经确定。填前缀最大值需要讨论:如果它本身已经确定,则没有限制,否则我们需要限制没有更小的数能够替代 \(i\)。稍微尝试一下可以发现,如果填 \(j\) 的位置在 \(nxt_i-1\) 之前,说明 \((j,i)\) 中的每个位置都已经确定,而填在前缀最大值位置的必然比 \(j\) 大,显然最小的就是 \(i\)。否则,\((j,i)\) 中的每个位置都已经确定,那么我们只需要判断能否把 \(j\) 换到前缀最大值位置,那么是 \((j,i)\) 中一定存在数在 \(nxt_i-1\) 之前。整合一下,如果当前位置不确定,转移的合法条件是 \([j,i)\) 中存在数在 \(nxt_i-1\) 之前。据此可以平方 DP。

注意到每次转移只需要修改单点(\(i\) 不是前缀最大值),或者对一些数乘 \(2\)\(i\) 是前缀最大值)。注意到乘 \(2\) 的点集相互包含,所以只需要动态把这些数加入集合,用线段树维护区间和即可。

提交记录 #679901 - Universal Online Judge (uoj.ac)

197 【PR 12】并查集

考虑怎么算贡献。合并 \((A_i,B_i)\) 的联通块时,考虑并查集树上连接两个联通块代表元 \(Ax,Bx\) 的边会被经过多少次。如果 \(Ax\) 的父亲为 \(Bx\),那么在合并 \(A_i\) 所在的相邻的联通块时,这条边会被经过。那么把 \(A_i\) 所在的联通块缩成一个点,设它的读书为 \(dA\),则贡献为 \(dA-1\)。另一种情况同理。

做 exchange argument,如果两个联通块的大小都大于 \(1\),那么把一个联通块的最后一次合并转移到另一个联通块一定不劣,所以一定有一个联通块的大小等于 \(1\)

写一下贡献可以发现这玩意就是 Monster Hunter 模型。枚举根大力做就可以了,复杂度 \(\mathcal{O}(n^2\log n)\)

Submission #338005 - Public Judge (pjudge.ac)

198【PR 2】史莱姆

可以莫队线段树判断做到根号。

考虑利用均摊优化。二分后设最开始的值是 \(w=a_i-k\),那么此时所有 \(a_j<w\) 的是平凡的,先把这些情况做完。否则 \(a_j\geq w\),此时若合法,那么 \(w\) 至少变为原来两倍,说明这种操作最多 \(\log V\) 次。使用主席树模拟可以做到 \(\mathcal{O}(q\log^2n\log V)\)

利用 \(2^k\) 值域分块描述上面的模型,我们每次需要加入在编号为 \(j<\text{highbit}(w)\) 的块中所有数的和,并查询第 \(\text{highbit}(w)\) 块中的最小元素(注意如果最小的是 \(i\) 我们需要查询次小值)。可以用 ST 表做到 \(\mathcal{O}(1)\) 查询。

我酱汁了,不会 RMQ,于是写了神秘维护次小值的单调栈+并查集做法。

Submission #339405 - Public Judge (pjudge.ac)

199【PR 2】背包

暴力 DP,设 \(f_{u,i,X}\) 表示割 \(i\) 条边,和根相连的权值和为 \(X\) 是否可行。可以 bitset 优化。

如果 \(w_1,w_2,w_3\) 满足 \(w_3-w_1\leq R-L\),那么 \(w_2\) 就没用,因为 \(w_1,w_3\) 至少有一个可以替换掉 \(w_2\)

这样状态数就是 \(\mathcal{O}(k)\) 的!!时间复杂度 \(\mathcal{O}(nk^3)\)

Submission #339594 - Public Judge (pjudge.ac)

200 loj3538. 「JOI Open 2018」冒泡排序 2

200!

结论是操作轮数是 \(b_i=\sum_{j<i}[a_j>a_i]\) 的最大值。

只有后缀最小值是有用的,所以只要考虑后缀最小值的逆序对数怎么求。

你注意到后缀最小值后面没有比它小的数,所以前面比它小的数就是全局比它小的数,我们每次要求出 \(i-f_{a_i}\) 的最大值即可,其中 \(f_{a_i}\) 是全局比 \(a_i\) 小的数量。

直接丢到权值线段树上维护。

LibreOJ (loj.ac)

posted @ 2024-02-26 16:28  yllcm  阅读(155)  评论(2编辑  收藏  举报