模拟赛简要题解(11.16-12.31)

进来的人能不能提醒我去补题啊啊啊。

11.16(C0389)

100+10+50=160,rk3。

本来 BC 都应该写出来的。

join

DP 或 贪心 都可以,贪心直接从下往上覆盖即可。

god

注意:这里的 \(\oplus\) 指的是按位或

合法条件可以化为判断是否存在 \(p\) 满足 \(\oplus_{i=1}^{p}a_i = \oplus_{i = p+1}^{n}a_i\)

继续挖掘。看到位运算肯定想到拆位,考虑每一位第一次和最后一次出现的位置。枚举或和相等的位置 \(p\),令第 \(i\) 位为 \(1\) 的最左边的数为 \(l_i\),最右边为 \(r_i\)。则 \(\forall l_i,r_i\) 满足 \(\bigcap\limits_{i=0}^{k-1}[l_i, r_i]\neq \varnothing\) 时为合法条件。此时的方案数为 \(((2^p-1)(2^{n-p}-1)+1)^k\),但是最后的 \([l,r]\) 可能会有多个 \(p\) 产生贡献,所以要减去 \(((2^p-2)(2^{n-p}-1)+1)^k\),即强制 \(l_i = p\)

最后还要加上一个 \(1\),因为全 \(0\) 也是可以的。

dust

life

11.17(C0390)

beast

直接贪心即可。

death

只会 \(\mathcal{O}(m^3\log m)\) 做法。

看到 \(n=10^9,m=200\) 是容易想到矩阵的。

考虑 dp。

\(f_{i, j}\) 表示填了 \(i\) 个数,前面有 \(j\) 个互不相同的数(包含 \(j\))。转移是容易的:\(f_{i, j} = (m - j + 1)\times f_{i - 1, j - 1} + \sum\limits_{k = j + 1}^{m - 1}f_{i - 1, k}\)

然后发现后面的东西可以直接矩阵优化,快速幂即可。

反正我是不会 \(\mathcal{O}(m\log m)\) 的做法的。

magic

大模拟,没调出来。

techn

原题 P4690

校内模拟赛大常数 \(\mathcal{O}(n^\frac{5}{3})\) \(3s\)\(2\times10^5\) 也是离谱。

11.22(C0392)

只有 154pts。

sort

先写一下赛时做法。

首先肯定要拆掉绝对值的符号,先把 \(x\) 离散化,然后发现按 \(w_i\) 从大到小的选择一定最优。但是发现如果这样会有点被多次选择,于是就会退化到 \(\mathcal{O}(n^2)\)

优化的话直接上势能线段树即可。

题解是直接拆掉绝对值解不等式,即变为两个恒等式:

\( \left\{ \begin{aligned} x_i-x_j\le w_i-w_j \\ x_j-x_i\le w_i-w_j \end{aligned} \right. \)

然后再变一下:

\( \left\{ \begin{aligned} x_i-w_i\le x_j-w_j\\ x_i+w_i\ge x_j+w_j \end{aligned} \right. \)

现在将 \((-x_i+w_i, x_i+w_i)\) 看作一个点,则变为删一个点就删去它左下角的所有点,排序后做一下就行了。

preprocessor

赛时为什么没有做出来呢?赛时为什么没有做出来呢?赛时为什么没有做出来呢?

你发现这个 \([S,T]\) 是很烦的,做一个容斥,分别统计 \(1\sim S-1\)\(1\sim T\)

然后把每个 \([A_i,B_i]\) 变成 \(2X_i+P_i\),这样就可以求出 \(X_i\) 的范围,也不需要考虑奇偶数了,然后还能求出 \(\sum X_i\) 的范围。

然后发现这玩意儿还是不好做,继续容斥。

因为很不爽的是这个 \(X_i\) 有上界,如果把上界去掉,就可以变为 \(X_1+X_2+\dots+X_n\in[L,R]\),同时减去所有下界,就变为 \(n\) 个非负整数在 \([L,R]\) 内,对 \([L,R]\) 再做容斥变成 \(1\sim L-1\)\(1\sim R\)。变为 \(\sum X_i\le V\)\(X_i\) 为非负整数。你这时候再加上一个数把小于变成等于,插板法即可。

tree

做一个树形 dp。

具体地,你发现点性质,然后就能知道就是把树的直径的中间的那条边给提出来,对两边分别作。

就分为路径经过和不经过直径讨论一下,经过直径的路径在套一个桶上去就行了,然后要预处理一下 \(rt_{1/2}\to u\) 的高度。

代码

last

11.24(C0394)

没打,还没有补。

11.27(C0398)

发烧了还没有好,直接垫底。

route

很简单其实但是我写的很麻烦。

当时在想两个点满足所有 \(1\sim i\) 时,路径上有 \(i+1\) 就很麻烦,当时是解决了,但是是否能形成路径这上面有点问题,不想调了,于是就换了一种写法。

直接统计 \(ans\) 的后缀和的数组就十分简单了,就可以最后进行一个查分,然后判断是否是一条路径可以判断每个点的度数,然后因为最多加入 \(n\) 个点,所以这里可以暴力向上跳,对 \(u\) 周围所有的 \(d\) 都进行更新即可。

seq

简单题,考场上因为头晕直接摆烂了,就只口胡了一下。

去掉所有平方因子是显而易见的。

先看 \(k=0\) 的情况。肯定想 dp,\(f_i=\min f_j+1\),条件是 \([j+1,i]\) 之间的数没有重复。但你这样是 \(\mathcal{O}(n^2)\) 的。然后优化挺显然,就是这个 \(f\) 单调递增,所以处理一个 \(pre\) 数组表示第 \(i\) 个数最前面的满足 \([pre_i+1,i]\) 无重复即可,这个 \(pre\) 显然可以预处理。

然后带修也差不多,处理 \(pre_{i,j}\) 表示第 \(i\) 个数经过 \(j\) 次修改后最前面能到哪,这个东西也比较好处理,dp 方程加一维带一个权就行了,复杂度变成 \(\mathcal{O}(nk^2)\)

game

如果胜负不确定,有最优策略这个东西就很难做。

但是你发现后手必胜,具体地待会儿证明,然后就只需要知道有多少最终态。

肯定如果有空格的话,一定是 A_B 或 B_A 的形式,因为 A_A 中间能填一个 B,两个空格怎么都能继续填。然后是个环,所以先拆成链,然后去掉空格肯定是 ABABABABAB,最后肯定不是 A,因为是一个环,然后枚举空格数组合统计一下即可。

tree

先咕一下。

11.29(C0400)

matrix

发现求的是矩阵和,先做一个差分变成前缀矩阵。

然后发现循环节长度不超过 \(100\),然后就会有很多的和是一个完整的循环节,这一段直接加上即可。

然后要求的就是剩余不是完整循环节的和。

然后如果只有一个询问是很简单的,多个询问的话,在线常数巨大。考虑离线扫描线,即将询问离线后从上往下扫(按 \(x\) 从大到小移动)。统计红色部分用一个桶 \(buc\) 表示循环节长度为 \(i\) 的值当前的完整循环节的和,然后再记录一个 \(sum\) 数组。其中 \(sum_{i, j}\) 表示行数小于当前 \(x'\) 长度为 \(i\) 的所有循环节的前缀和,因为这些的剩下部分的长度是一样的,可以直接计算。时间复杂度:\(\mathcal{O}(r\min(c,100))\)

number

容易发现这个最后的数如果不产生进位的话是回文的,然后就可以直接枚举两端,然后再判断对每一位进不进位。注意如果最高位进位的话需要单独考虑。

如果不想清楚的话会非常麻烦,但是这种形态是类似于 数位dp 的,记忆化搜索即可,实现稍有细节。

提交记录

sort

快速算贡献肯定是对每一个人进行考虑的,考虑每一个人能使多少人向后移动,钦定必须因为他才向后移动,这样就不会存在 \(i, j\) 使 \(j\)\(i\) 贡献了多次。

然后 \(\ge x\) 的肯定不影响,所以值为 \(x\) 的若干位置只会贡献它们之间小于 \(x\) 的数的个数。

但是这个东西是有后效性的,因为 \(<x\) 的数会被移到最后。但是发现这些 \(<x\) 的数在环上的相对位置没有改变,并且 \(\ge x\) 的数不会被统计到,于是就只需要实时维护环的起点。小于 \(x\) 的数的个数非常好维护,因为是按照值从大到小考虑的,就等于已经离线了,所以只需要树状数组维护区间和了。

pool

没补。

12.1(C0402)

string

这道题说难不难,说简单也不简单。

赛时的理解很感性。类似于 \((a+b)^2\ge a^2+b^2+1\) 的感觉,就让前面 \(k-1\) 个堆在一起,最后一个放在剩下的空白处的最中间。然后注意判掉 \(k=0\) 的情况。

大概就是因为比如要放两个,然后放的位置是 \(x,y(x<y)\)。贡献就是 \(x(y-x)+(y-x)(n-y+1)=(y-x)(n+x-y+1)\),然后就之和 \(x-y\) 有关了。三个也差不多:\(x(y-x)+(y-x)(z-y)+(z-y)(n-z+1)+x(n-z+1)=(x-y+z)(n-z+y-z+1)\),就之和 \(x-y+z(x<y<z)\) 有关了,换元变为 \(p(n-p+1)\),由二次函数可知 \(p\) 取多少时达到极值。所以取 \(x=1,y=2,z=\lceil\frac{n+2}2\rceil\)。然后这样可以推到多个。多个就是对以每个位置作为长为奇数的区间的中心求贡献,发现可以合并就行了。

题解的意思大致是说令“怪”的词是 \(1\),然后做一个前缀异或和,\(s_i\neq s_j(i<j)\)\([i,j]\) 是一个合法区间。所以设 \(0/1\) 的个数是 \(x/y\),然后又因为 \(x+y=n+1\),然后就按刚刚的算法就行了。证明就不是区间而是单点了,就会方便很多。

统计是非常简单的。

题解的做法用到了一个 遇到奇偶相关的构造可以考虑用异或前缀和来解决 的 trick。

artist

赛时想到建树了但是忘了启发式合并了,加训!

发现他给的区间要么包含,要么无交。遇到这种东西可以考虑建树,即从包含它的区间连向它。剩下的东西其实就非常简单了。然后如果 \(u\) 的儿子 \(v\) 所维护的区间 \([L_v,R_v]\) 已经得到答案了,则将儿子的颜色集合合并到 \(u\),这里需采用启发式合并。就是因为如果 \(u\) 有儿子没有得到答案,\(u\) 也不会得到答案。所以只有当其儿子完成贡献时再将颜色集合合并到 \(u\),而不用在 \(rt\to u\) 的路径上都更改颜色了。

是否得到答案这个东西可以用一个 umap 维护,记录出现的数的种数是否等于 \(r-l+1\) 即可。

tree

看到一棵树的价值是同色点的距离最大值,肯定考虑枚举这个最大值是多少。如果觉得不是很一眼的话,可以想一下链的部分分。

首先肯定就要先处理出一条直径出来,然后如果直径的两端点同色肯定贡献就是直径了。不然的话就枚举长度 \(d\)。令直径的两端点为 \(p,q\),所有离 \(p,q\) 的距离大于 \(d\) 的点肯定与 \(p,q\) 异色。然后如果存在点 \(u\) 满足 \(\max(dis(u,p),dis(u,q))\le d\)。那这个 \(u\) 就两个颜色都可以。

然后你从大到小的枚举 \(d\) 就可以了,因为要求异色,所以之前要求异色的点后面也会异色,于是均摊是对的。

预处理 \(2\) 的幂可以做到线性。

rugby

暂时不会。

山东省集 NOIP 九连测

12.5

100+30+0+0

kitty

首先有一个显然的 dp,\(f_i\) 表示跳到前 \(i\) 个点的方案数,则有 \(f_i=1+f_{i-1}+f_{i-2}+f_{i-k}\)。然后发现 \(k\le 100,n\le 10^9\),矩阵加速即可。

string

发现其实可以找出两个相同的子序列,设第一个和最后一个的位置分别是 \(l,r/l',r'\),则有 \(r\le l'\),因为 border 的长度不会超过 \(\lceil \frac {n}{2}\rceil\)。不妨先枚举 \(l'\),然后因为最后的答案和长度有关,记 \(f_{i, x, y}\) 表示在当前的 \(l'\) 的情况下 \(r = x, r' = y\) 的方案数。则答案为 \(\sum i\times f_{i, x, y}\times 2 ^ {\max(0,l' - x - 1)}\),转移是简单的。前缀和优化可以使 dp 部分的复杂度变为 \(\mathcal{O}(n^3)\),这样的复杂度就是 \(\mathcal{O}(n^4)\),考虑优化。

发现其实并没有必要记录每一个每一个长度 \(i\),可以转为记录 \(i\) 的和,即再记录一个 \(g_{x, y}\) 表示在当前 \(l'\) 的情况下 \(r = x, r' = y\) 的长度和。有转移 \(f_{x, y} = \sum\limits_{x'=1}^{x-1} \sum\limits_{y'=1}^{y-1} f_{x', y'}\)\(g_{x, y} = \sum\sum g_{x', y'} + f_{x', y'}\),类似于将一次性的转移了 \(f_{i, x, y}\)\(i\) 统一转移了,然后这个东西显然的用二维前缀和优化,最后答案就是 \(\sum \sum [s_x = s_y]g_{x, y}\times 2^{\max(0,p - x - 1)}\)。算上枚举 \(p\),时间复杂度为 \(\mathcal{O}(n^3)\)

提交记录

contact

一看这个关系就很复杂,考虑转化为图论。

转为图论后题意就变为了:给定若干点集,点集内的点两两连边,边权为点权之积,求一个边权和最大的无重边(基环树)森林。

类似于 Kruskal,然后发现 \(|s_i|\le 100\),所以可以在点集内暴力建边,然后要求无重边,考虑到基环树森林不好判断重边,可以在排序后去重。但是发现不能像 MST 那样用一条边去合并两棵基环树,当 \(fa_u \neq fa_v\) 的时候判断一下当前 \(u, v\) 的连通块是不是都是基环树,如果是就跳过就行了。

提交记录

bipolar

先考虑怎么判定一个 DAG 的游戏数量的奇偶性。记 \(f_i\) 表示以 \(i\) 结尾的游戏数,然后就是看 \(\sum f_i\) 的奇偶性,发现 \(f_u = \sum\limits_{(v, u)\in E} f_v\),所以只需关注后继为 \(u\)\(f_v\) 为奇数的数量。

考虑如何统计满足条件的 DAG 的数量。记 \(f_{i, x, y}\) 表示 前 \(i\) 个点中,有 \(x\) 个红点满足以它们结尾的路径数量为奇数,有 \(y\) 个黑点满足以它们结尾的路径数量为奇数 的图的数量。

然后分别考虑 \(i + 1\) 分别为 红/黑 且 结尾的路径数量是否是奇数的情况。以红点,且 \(x,y\) 不变为例,直接转移发现系数为 \(2^{y - 1}\times 2^{i - y}\),即除开 \(x, y\)\(0\) 的情况,系数均为 \(2^{i - 1}\)

于是容易得到新状态 \(g_{i, j, a, b}\),表示前 \(i\) 个点,\(x + y \bmod 2 = j\)\(x / y\) 是否非零的方案数。对于一般情况显然 \(g_{i + 1, j, 1, 1} = (g_{i, 0, 1, 1} + g_{i, 1, 1, 1})\times 2^{i - 1}\)\(xy = 0\) 的情况单独考虑一下即可。

提交记录

12.7

100+65(100)+10(100)+0

挂了巨大多的分。

decimal

发现每一位都是 \(\times 10\) 之后对 \(m\) 取模,快速幂求出第 \(L\) 位的值然后递推即可。

labor

首先冒泡次数是等于逆序对数的。然后当 \(l\) 固定的话,冒泡次数是不减的。所以可以直接上双指针,并用一个维护值域的 BIT 统计即可。时间线对。

提交记录

distance

发现给的条件是通过最少的一些操作,使得点 \(i\) 是重心,求最小操作数。

一个比较正常的想法就是对于每一个 \(i\) 以它为根重新遍历一遍,但是这样需要记录所有点的 \(sz\),还要判断接下来取的是否已经被删掉,很麻烦,但是如果 \(sz_u\le \frac{n}{2}\),则 \(\forall v\in subtree_u\)\(sz\) 就都不需要记录了。

发现本来就是求重心相关,于是按照重心考虑,根据重心 所有子树不会超过 \(\frac{n}{2}\) 的一半 的性质,就只有 \(sz_v - sz_u(v\in son_{rt}, u\in subtree_v)\)\(sz_v(v\in son_{rt},u\notin subtree_v)\) 有用,所以可以直接从大到小的去取,用一个维护值域的线段树,在上面二分即可。

worship

暂时还不会。

posted @ 2023-12-27 15:50  Pengzt  阅读(33)  评论(0编辑  收藏  举报