record 4.29-5.3
[CF1965 B]
简单题。但是中间脑子不清醒想了一会。
这个其实就是 multiset 凑数,我们非常清楚可以先排序,然后依次向后扩展就可以了。
我们要凑出来 \([0,k-1]\cup[k+1,n]\)。第一步肯定是先凑出来 \([0,k-1]\),然后给它加上一个 \(k+1\),变成 \([0,k-1]\cup[k+1,2k]\),然后考虑在接下来的所有数都 \(>k\) 的条件下凑出来 \([k+1,n]\)。
怎么凑呢?你如果直接扔一个 \(2k+1\) 上去,发现变成了 \([0,k-1]\cup[k+1,3k]\cup[3k+2,4k+1]\),中间多出来一个空格 \(3k+1\)。为了处理这个空格,直接的想法是扔一个 \(3k+1\) 上去,你发现变成了 \([0,k-1]\cup[k+1,6k+1]\cup[6k+3,7k+2]\),仍然多出来一个空格,再扔一个 \(6k+2\) 上去。
进一步,如果你把代码写出来,你发现这个空格的位置 \(x\) 是每次翻倍的,所以我们大概就可以做到 \(\log\)。
* [CF1965 C]
首先我们找一下一个折叠是合法的充要条件,你发现是相邻两个折叠段必须小的那个能完全翻到大的上头。
然后我们找一下一个合法折叠的答案是多少,你发现是整个长度减掉所有相邻段长度的最小值。
然后你就会一个 dp 了,复杂度大概是 \(O(n^2\log n)\)。
但是这个烂完了。然后我们看到 tag 里有贪心,所以我们猜一手:任意一个合法折叠方案都是最优折叠方案的子集。换句话说,我们只要能折叠就折叠,直到不能折叠为止,这就一定是最优的。
阅读了 sol。
我们发现,如果在所有相邻两个数相同的位置折叠,那么我们可以得到一个合法解。这个合法解没有相邻两个数相同,并且为了让最后的解没有两个数相同,我们必须在所有相同数之间折叠。所以只有这一个解,满足条件。
然后我们考虑任意一个合法解,如果它有相邻两个数相同,那我们可以继续折叠,得到更优的解。所以上面那个解是最优解。
* [省选联考 2024] 迷宫守卫
我们先想想 \(Q_1\) 怎么求。
你可以 dp 出来 \(f_{u,x}\) 表示 \(u\) 子树内,为了让可行点 \(\ge x\) 需要付出的代价。转移
这部分是可以求出来的。
然后你只需要二分 \(f_{u,x}\le K\) 的位置就可以找到 \(Q_1\) 了。接下来的问题是,在保证 \(Q_1\) 取到的前提下,最小化字典序。
你考虑,把 \(rt\to Q_1\) 这个链提取出来,其实分成了若干个(并不独立)的子问题。这里并不独立是因为它们需要共同保证 \(Q_1\) 能取到。
唉反正看过题解了,我只能感觉有道理,但是不是完全清楚。这个题好像跟 d1t2 很像来着,有时间把它们都看看。
[CF 1969] F
这个题,可能是 dp/贪心/flow。
初步想法是你先找一个匹配方案能合法的充要条件。你发现限制匹配合法的就是手中有 \(k\) 张牌,而这个要求等价于,跨过任意一个位置的匹配数量 \(\le k\),或者说,在 \(k\) 之前结束的匹配 \(\ge 1\),在 \(k+2\) 之前结束的匹配 \(\ge 2\),一类的东西。
这个其实不是非常好,我们更想要一个给一个匹配的一部分,问能不能合法的充要条件。也可以,这相当于是在 \(k+2i\) 之前结束的匹配至少要有 \(i+1-\lfloor\frac e2\rfloor\),其中 \(e\) 表示之前的未匹配点个数。
再来一点观察。发现两个相同的数进行匹配只可能发生在相邻出现之间,否则我们可以调整。
写了个假贪心,看了眼 jiangly 的代码,感觉有点牛了。不太会。
[APIO 2023] 赛博乐园
简单题。
观察到“除以 2 的能力”使用 \(20\) 次之后,前面部分会除 \(1048576\),这基本上超出了精度要求,所以可以忽略不计。换句话说,如果我们使用了超过 \(20\) 次能力,我们可以只使用最后 \(20\) 次,效果不变。
那我们建立分层图,从一个超级源点向所有 \(ar=0\) 的点以及起始点连边跑最短路就可以了。
* [APIO 2023] 序列
这个题就是让你,算所有的 \(l,r\),\([l,r]\) 中位数出现次数的最大值。
也就是 \(\max_{l,r}\max_{x}[x\in S(l,r)]count(l,r,x)\)。
有一个非常自然的想法是枚举 \(x\),我们考虑 \(x\) 是某个区间 \([l,r]\) 中位数的充要条件。
那套路就是把 \(\ge x\) 的当成 \(+1\),把 \(<x\) 的当成 \(-1\),这就要求 \(s_r-s_{l-1}=0/1\),而 \(count\) 显然有区间包含单调性,所以我们对 \(s\) 的每个值只会算一个 \(count\)。但是这复杂度仍然爆炸。
我们换个角度,考虑找到所有 \(x\) 的位置。
你发现如果 \(s_r=s_{l-1}\),那么 \(s_r\) 一定是某个 \(x\) 的出现 \(p\) 的 \(s_p\),否则的话,相当于没有被“卡住”。类似地,如果 \(s_r=s_{l-1}+1\),那么其中一定有一个是 \(s_p\)。所以我们只需要检查这些 \(s\) 的答案。
额我不清楚这结论对不对,我们先当它是对的。
然后我们考虑怎么计算答案,你发现你现在要做的就是给定一个 \(v\),问你 \(s_i=v\) 的最靠左/右的都是啥,以及支持修改前缀和。
我们注意到,\(s\) 的变化是连续的,所以我们只需要维护这个区间 \(s\) 的 \(mn,mx\) 就可以知道这个区间是否有 \(v\),那就可以做了。
简单做到 1 log。
我烂完了。啥都不会。
你考虑把这个中位数条件写清楚一点。发现要求 \(v_0+v_1\ge v_{-1},v_{-1}+v_{0}\ge v_1\),也就是说分别把 \(0\) 看成 \(1,-1\) 都要比另一个大。
记两种前缀和分别是 \(s_i,t_i\),等价于要求 \(s_r\ge s_{l-1},t_r\ge t_{l-1}\),并且要求 \(v\) 在这个区间中出现过,但是后面这个条件可以松掉。
考虑前面这东西怎么做,这是个偏序的形式,而且 \(s,t\) 是连续的,所以我们提取出来所有 \(a_i=v\) 的位置,然后对这些位置询问它们前后缀 \(s,t\) 的 max/min,这样 \([l,r]\) 可以被包含就等价于 \(premins_{l-1}\le sufmaxs_r,premint_{l-1}\le sufmaxt_r\),这些都是可以线段树维护的,我们相当于要对每个 \(r\) 求出来最小的 \(l\),这个也不难算,这是二维偏序最值的问题,转成一维就可以做了。
你可能会觉得这个转化成 \(premin,sufmax\) 什么的不一定是充要的。其实在本题情况下确实是充要的,因为本题你在坐标轴上画出来是若干个斜率为 \(-1\) 的线段,中间用斜率为 \(1\) 的线段连接,然后你相当于想知道能否在两条线段上各找一个点满足偏序关系。然后你发现就是这个样子的。
思路其实挺清晰的,感觉以后还是要把那些“之后想想就清楚的”给先想清楚,仔细写好,不能马虎。
[CF 1967] B2
设 \(a=a'd,b=b'd,(a',b')=1,a'\le\frac nd,b'\le\frac md\)。
条件等价于 \(a'+b'\mid b'd\),换言之,\(\exist k\ge 1,k(a'+b')=b'd\),也就是 \(ka'=(d-k)b'\),而 \((a',b')=1\),所以 \(k=tb',d-k=ta'\) 也就是说 \(d=t(a'+b')\)。
所以现在要统计的就是 \((a',b')=1,a'(a'+b')\le\frac nt,b'(a'+b')\le\frac mt\) 的 \((a',b',t)\) 的数量。
考虑枚举 \(t,a'+b'=x\),这相当于要求 \((a',b')=1,a'+b'=x,a'\le\frac n{tx},b'\le\frac m{tx}\)。
然后你简单分析一下发现 \((a',b')=1\iff(a',x)=1\iff(b',x)=1\)。
所以我们可以做了。你记 \(f(n,x)=\sum_{i=1}^n[\gcd(i,x)=1]=\sum_{d\mid x}\mu(d)\lfloor\frac nd\rfloor\)。
但是这个写得不严谨,你要要求 \(\min(x-1,\frac n{tx})\ge \max(0,x-\frac m{tx})\)。
这样的 \(t\) 只有 \(\frac{n+m}{x^2}\) 个。所以我们直接枚举,然后暴力算 \(f\) 就可以了。复杂度 \(\sum_{x=1}^{n+m}\frac{n+m}{x^2}x=O((n+m)\log(n+m))\)。
为啥多项式前缀和之后次数升 1
考虑多项式 \(f(x)\) 以及它的前缀和 \(g(x)=\sum_{i=1}^{x}f(i)\)。
注意到,我们可以把 \(f(x)\) 的每一项单独求前缀和,所以现在 \(f(x)\) 退化为 \(f_a(x)=x^a\)。
前缀和之后 \(g_a(x)=\sum_{i=1}^xi^a=\sum_{i=1}^xif_{a-1}(i)=\sum_{i=1}^xi(g_{a-1}(i)-g_{a-1}(i-1))=xf_{a-1}(x)-\sum_{i=1}^{x-1}f_{a-1}(i)=xg_{a-1}(x)-g_{a-1}(x-1)\)。
考虑使用归纳法,我们对 \(g\) 进行归纳,\(g_{a-1}(x)\) 是 \(a-1\) 次多项式,如今又乘了一个 \(x\),所以 \(g_a(x)\) 是 \(a\) 次多项式。
那么就成立了。
[CF 1967] C
你一看这个东西,先打表找规律。
首先这东西有一个封闭性,就是说 \(x\) 进行 \(k\) 次操作后,它的值仍然只跟 \(a_{x-\text{lowbit}(x)+1\sim x}\) 有关。
这说明所有的系数个数不超过 \(O(n\log n)\) 个。我们就可以尝试把所有的系数求出来了。
然后看一眼打的表,发现同一个位置上随着 \(k\) 的增加似乎是关于 \(k\) 的若干阶前缀和的形式。这个若干阶你发现是可以求出来的。
这个前缀和我们都知道它可以表示成阶数次数的多项式,我们把多项式插出来,就可以做了。
~ [CF 1967] E1
你分析一下,发现我们只关心能走得最高的那一个 \(b\) 是怎么走的。这就很自然地给出了一个 \(O(nm)\) 的 dp。
然后你冷静分析一下,你发现这个东西本质上就是个格路计数。你考虑枚举一个终点,然后你发现就是不能经过 \(y=m,y=-1\),并且每向上走一步就有 \(m-1\) 的贡献,往下走一步就有 \(1\) 的贡献。枚举终点,贡献是事先确定的。
问题转化成给定一个终点 \((n,x)\),从起点 \((0,b_0)\) 不能经过那两条直线有多少条路。这个是经典的反射容斥,但是我并不是很清楚。
现在清楚了。
你考虑我们会算什么。我们把两条直线分别叫做 \(A,B\),如果我们先关于 \(A\) 对称,算出来的就是 \(*A*\),也就是说路径中至少经过一个 \(A\)。
你可能会想能不能算一个 \(B\) 出来,但是这东西并不好算。
如果我们再关于 \(B\) 对称呢?算出来的是 \(*[B][A],*[B][A][B]\),之前算出来的也可以写成 \(*[A],*[A][B]\),这里就是在前面多加了一个 \([B]\)。
这就很有趣了。你可以继续关于 \(A\) 对称,你也可以先关于 \(B\) 对称生成一个类似的东西。然后你任意写一个经过的序列,比方说 \([A][B][A][B]\),比方说 \([A][B][A][B][A]\),你发现,给之前的方案凑一个 \((-1)^i\) 容斥系数就能得到你想要的东西。
而由于对称会让终点越来越远,所以迟早我们没有任何办法到达终点。事实上,每对称一次,距离增加 \(O(m)\),所以有用的项只有 \(O(\frac nm)\),结合 \(O(nm)\) 的算法我们可以得到一个 \(O(n\sqrt{n})\) 的做法。
* [CF 1967] E2
这个东西,你想一下,感觉就是拆一拆贡献什么的。然后写出来之后发现要算组合数前缀和,这是经典没法做的东西,所以就寄了。
但是,你发现我们可以先进行一步转化。我们之前还要枚举,如果一个点提前到达了 \(y=m\),说明这之后怎么选都没用了。但是我们也可以不枚举这个,改成直接算走到任意一个终点的权值。你算一下发现是对的。
所以现在,问题变成了,从 \((0,b_0)\) 出发,每次可以右上或者右下,为空集或者开头为 \(A\) 的路径权值。
开头为 \(A\),其实就是 \(f(\varnothing)-f(B)+f(AB)-f(BAB)+\dots\),你把式子列出来,目标转化成求出每个组合数前面的系数。
你发现差分就可以做了。但是这东西还要考虑终点不在两条直线之间的情况,非常麻烦,一点不想写。
~ [APIO 2020] 粉刷墙壁
简单题,但是我很蠢。
注意到题目限制里的 \(\sum f(k)^2\) 的限制非常奇怪,我想了很久有什么做法是跟 \(f(k)^2\) 有关的,发现想不了一点。
后来看了讨论发现这个东西就是告诉你 \(\max f(k)\le\sqrt{400000}\)。
那我们就会了。你从前往后扫,维护每个方案能匹配多长的末尾。显然这个位置都匹配不上的都是 \(0\),这个位置匹配得上的,匹配长度 \(+1\)。
这样你就可以知道每个段有没有合法方案。然后我们贪心就知道最好解了。
* [APIO 2020] 有趣的旅途
首先这个 \(deg\le 3\) 其实就是说这东西基本上是一棵二叉树,或者说存在一个点,使得以这个点为根的时候,这个树是二叉树。
但是它让你算的这个东西仍然十分离谱啊,它要让距离单调不升。你肯定得先想想给你一棵树怎么做。
一个直接的想法是我们先找出来直径,然后从一个端点走到另一个端点,把这个端点删掉,再找直径(可以证明一定存在以这个点为端点的直径)的另一个端点再走过去就行了。
因为你在不断删点,所以直径的长度是单调不增的,那么这个东西确实是对的,但是现在我们的复杂度是 \(O(n^2)\)。
阅读了 sol。之前的思路错了。
我们考虑给定一个根,然后你怎么做。发现可以在三个子树内交替选深度最大的,并且跟上一个选的不在同一个子树里的。但问题是可能子树大小并不平衡。所以我们可以选择重心当成根。
找重心,先随便钦定一个根,然后得到所有子树的 sz,找到 \(n-sz\le\frac n2\) 的 \(sz\) 最小的点就可以了。
找到重心 \(G\) 之后,我们还需要知道其它所有点到 \(G\) 的距离,以及它们在哪个子树里。
这个可以通过询问它们到三个孩子的距离,就能判断它们在哪个子树里。
* [AGC 009] D
神秘题目。
考虑点分树的另一种定义方式,你给每个点一个标号,然后要求任意两个相同标号之间至少有一个比它大的标号。现在要让你最小化最大标号。
考虑任意选一个根,然后开始贪心。对每个子树,你算出来子树的答案,以及这个子树里还有哪些标号没有符合条件。
然后你考虑自己标号成什么东西。首先子树不符合条件的肯定没法标,然后就是如果有两个子树标号 \(x\) 都不符合条件,那我们至少要标 \(x+1\)。找到满足这个条件的最小的 \(x\) 并相应更新不符合条件的标号就可以了。
~ [ARC 114] D
首先这个操作次数,显然我们的最优操作策略是,每次刷全局最小值,然后递归到两侧继续刷。
这东西很有子结构,考虑 \(dp_{n,m}\),转移枚举最小值,然后还要做另一个 dp 算最小值位置,这样就可以转移了,\(O(n^3)\)。
考虑优化的话,你发现“另一个 dp”可以写成多项式求逆的形式,复杂度可能是 \(O(n^2\log n)\)。不用管这个东西。
另一个方向是,我们先当所有方案都是 \(n\),然后考虑每个结构给答案带来的贡献。
具体来说,如果有一个长度为 \(x\),最小值为 \(v\)(左右都紧挨着一个 \(>v\) 的数)的结构,并且这个结构当中有 \(y\) 个位置取到最小值,那么它对答案就会有 \(-(y-1)\) 的贡献。
所以
显然最后那部分可以提前计算,总复杂度 \(O(nm)\)。
* [CF 1969] F
sol 写得非常清楚了。
我一开始在想一些贪心,然后发现是假的。其实贪心假了就是你发现这个决策不一定是最优决策,那你不妨枚举选择哪个决策,然后继续往后算,这样就能得到这个解了。
后面的优化,还可以,不算特别逆天。

浙公网安备 33010602011771号