ATC/CF round vp 选记
CF2163D2. Diadrash (Hard Version) *2500
有一个隐藏的 \(0\) 到 \(n-1\) 的排列,初始给定 \(n\) 和 \(q\) 个区间 \([l_i,r_i]\),你可以至多询问 \(30\) 次每次查询排列的一个区间的 \(\mathrm{mex}\),用来找到这 \(q\) 个区间的 \(\mathrm{mex}\) 的最大值。\(n \leq 10^4,q \leq 3 \times 10^5\)。
首先把被包含的区间踢掉,剩下的区间按 \(l\) 为关键字排序后 \(l,r\) 分别递增。
考虑对于排列 \(\mathrm{mex}\) 的一个性质:\(\mathrm{mex}(l,r)=\mathrm{min}(\mathrm{mex}(1,r),\mathrm{mex}(l,n))\)。那么 \(\mathrm{mex}(1,x),\mathrm{mex}(x,n)\) 两个函数一个不减一个不增,取 \(\mathrm{min}\) 后显然可以三分,注意到是整数函数,可以用二分替代,每次要询问两个函数对应点的值,\(2\mathrm{log}\ n=30\)。
CF2165D Path Split *?
给定一个长度为 \(n\) 的子序列,要将它划分为若干子序列,满足子序列内相邻差值绝对值都等于 \(1\),求划分出的最小子序列数量。\(n \leq 10^6\)。
感觉是不难的题。显然如果对所有 \(|a_i-a_j|=1\) 的 \(i,j\) 连边就是要求最小链覆盖,先转一手二分图最大匹配。
显然不能直接跑最大匹配,那基本就是贪了。枚举二分图左部点,然后来配右部点。可以发现 \(1\) 可以配的是最弱的,剩下的优先级就是按大小来。然后对于一个值 \(v\) 来说,\(v+1\) 后面还有人配,而 \(v-1\) 再往后扫就没人可以配了,所以对于每个点优先配 \(v-1\) 再配 \(v+1\)。那对于同一个数值比如说 \(v-1\) 我配哪个呢,显然是配最近的,要不然正确性没法保证。用 set 维护这个过程即可。
CF2048I1 Kevin and Puzzle (Easy Version) *3500
给定一个只包含 L,R 的字符串,要求构造一个数组 \(a\),满足对于 \(s_i=L\) 的位置,\(a_i\) 等于其左侧不同数种数,对于 \(s_i=R\) 的位置,\(a_i\) 等于其右侧不同数种数。
\(n \leq 10^5\)。
非常好的归纳构造题,使我的大脑旋转。
算是某种程度上独立思考出来了?
直觉告诉我们肯定得按照某个顺序决策 \(a\) 的值,然而你发现不管是顺着做还是倒着做都非常 Hard。
于是,我们考虑从外层开始确定 \(a\) 的值,即每次决策首尾。
-
若 \(s_1=R,s_n=L\),直接让所有数等于 \(1\) 即可。
-
若 \(s_1=L,s_n=R\),此时显然有 \(a_1=a_n=0\),对于中间的 \(a_2,a_3,...,a_{n-1}\),假设我们已经保证它们内部平衡,那么只需要让它们所有数加 \(1\) 就能把 \(a_1,a_n\) 塞到两边使得整个数组依然平衡。
-
若 \(s_1=s_n\)。不妨假设 \(s_1=s_n=L\),首先有 \(a_1=0\),然后考虑决策 \(a_n\) 的值,这一点不太容易,因为还不确定中间的值,如果确定了可以使得中间内部平衡的值,那么我们令中间所有数加 \(1\),然后令 \(a_n\) 为此时前面数的最大值加 \(1\) 即可。为什么这里令 \(a_n\) 为最大值加 \(1\) 就是对的呢?观察过程,可以发现 \(a\) 值是连续的,因此可以直接这样做。
具体实现的时候直接递归,记录当前递归的区间要加多少,然后回溯的时候返回一下当前所有数的最大值即可。
CF2147E Maximum OR Popcount *2300
给定一个长度为 \(n\) 的数组 \(a\),有 \(q\) 个独立的询问,每次给出 \(b_i\),你可以操作至多 \(b_i\) 次,每次给一个 \(a_i\) 加一,求最后所有数的 or 的 popcount 最大值。
我们考虑把一个数加到拥有某一个它原本没有的 bit 位需要多少代价,显然就是比这个位低的所有位组成的数假设为 \(x\),那么代价就是 \(2^{bit}-x\),容易发现这个代价随着 \(bit\) 变大而变大。因此我们在询问操作的时候一定是尽量给小的位弄成 1,如果不够用了就寄了。
然而我们发现因此策略是固定的,所以所有数的 or 只有 \(O(log\ V)\) 种,所以可以直接预处理每一种的最小代价,查询的时候二分下即可。
注意一件事情,每一次把一位弄成 1 以后,答案的 or 里面更低的位可能变成 0,所以在固定了操作的 1 的前缀以后可以从后往前扫,每一次如果当前位是 0 就操作一下。
CF2147F Exchange Queries *2800
有两个长度为 \(n\) 的排列 \(s,p\),如果 \(s_i>s_j\) 或 \(p_i>p_j\),那么就可以把物品 \(i\) 换成物品 \(j\),有 \(q\) 次操作,每次交换 \(s\) 或 \(p\) 中的两个数,交换完成后询问当前情况下有多少对 \((i,j)\) 满足 \(i\) 能换若干次后换成 \(j\)。\(n,q \leq 10^5\)。
首先把 \(i\) 能换成 \(j\) 的关系变成一条 \(i\) 连向 \(j\) 的有向边,那么原问题就是求可达点对数量。直接求显然不行,我们看看这个图有什么性质。考察一对 \((i,j)\),显然它们之间 \(i \to j\) 和 \(j \to i\) 必然至少连了一条,所以这个图是一个竞赛图加上一些边,因此缩点后肯定是一条链,显然对这个做可达性是简单的。
所以现在就是要找到每个强连通分量的点数以及它们在链上的排列顺序。我们先把所有物品按 \(p_i\) 排序,那么此时所有 \(j>i\) 都有 \(j \to i\) 的边,那么我们只需要考虑 \(i<j\) 的 \(i \to j\) 的边来配合从后往前连的边来缩点即可,容易发现此时只有 \(i<j,s_i>s_j\) 的满足,并且对于满足 \(s_i>s_j,i<j\) 的 \(i \to j\) 我们还知道一定有一条 \(j>i,j \to i\) 的边,因此我们可以把所有这样的 \(s\) 的逆序对看成无向边,然后直接缩。
我们考虑先找出第一个位置所在的连通块,考虑不停加点进来,那么对于后面的一个点,如果能加进来,当且仅当现有的连通块里面有大于这个点的值。可以发现它所在的连通块一定是一个前缀,证明考虑:假设现在连通的前缀是 \(1 \to x\),现在可以加进来一个 \(y\),但是 \(y \ne x+1\),也就是说直接加连通块不构成前缀。我们假设 \(a_z>a_y,z<y\) 即是 \(a_z\) 把 \(a_y\) 加进来的,此时我们对于 \(i=x+1,x+2,...,y-1\) 的点也就是 \(x,y\) 中间的点,如果 \(a_i \geq a_y\) 那么和 \(a_y\) 构成逆序对,可以加入连通块,若 \(a_i<a_y\) 则 \(a_i<a_y<a_z\),显然也可以用 \(a_z\) 把它加进来。
类似的,我们也可以容易的说明所有连通块都是连续的一段。
因此,我们只需要找到块之间的断点即可刻画出这个缩点后链的结构,
先找到第一个断点,显然当前缀中没有任何数可以后后面的数组成逆序对就会断,也就是会在说会在第一个 \(\mathrm{max}_{j=1}^i a_j=i\) 的位置后面断开,以此类推,所有断点都满足这个东西。
我们把断点拎出来,设为 \(b_1,b_2,...,b_m\),假设 \(b_0=0\),那么第 \(i\) 个连通块(对应有向图中的强连通分量)就是 \([b_{i-1}+1,b_i]\),然后对于第 \(i\) 个连通块内的点就可以到达 \([1,b_i]\),所以答案就是 \(\sum_{i=1}^m b_i \times (b_i-b_{i-1})=\sum_{i=1}^m b_i^2-\sum_{i=1}^m b_{i-1}b_i\)。考虑来维护这个东西。
我们令 \(a_i\) 表示 \(i\) 这个前缀比 \(i\) 大的数的个数,那么 \(b\) 里面其实就是所有 \(a_i=0\) 的 \(i\)。交换一次的影响对 \(a\) 来说首先可以认为是两次单点修改,一次单点修改对 \(a\) 的影响就是把一个后缀 \(+1/-1\)。然而直接维护值等于某个数的下标信息是困难的,然而注意到 \(0\) 是全剧最小值,而维护最小值的下标信息是可合并的,是好维护的,所以直接上线段树即可。
利用这个做法还可以通过 CF1270H
CF628E Zbazi in Zeydabad *2300
给定一个 \(n \times m\) 的只包含 \(Z\) 和 \(.\) 的矩阵,问 "Z形" 的出现次数,定义懒得写了,见原题。\(n,m \leq 3000\)。
挺有意思,但是简单。肯定先得固定一条横的或者斜的,考虑固定斜的,那么就枚举这条斜的的左下角。预处理每个点向右上,左,右的最长连续 z 长度 \(f_{i,j},g_{i,j},h_{i,j}\),那么正方形变长一定 \(\leq \mathrm{min}(f_{i,j},h_{i,j})\),然后还有这个斜线的右上角的 \(g\) 有一个限制,随便做下数点就行。
CF2122D Traffic Lights *2400
给定一个包含 \(n\) 个顶点 \(m\) 条边的简单无向连通图。
初始时刻(第 \(0\) 秒时),令牌位于顶点 \(1\)。设经过 \(t\) 秒后令牌位于顶点 \(u\),每秒必须选择执行以下操作之一:
- 等待 \(1\) 秒;
- 花费 \(1\) 秒,让令牌沿顶点 \(u\) 的第 \((t\bmod \text{deg}(u)+1)^*\) 条边移动(边的顺序按照输入顺序排列)。
请计算从顶点 \(1\) 到顶点 \(n\) 的最短总耗时,以及在总耗时最短的前提下能够实现的最小等待时间。
刚打完 NOIP,累了,困了,所以直接粘下洛谷的题意。
首先有一个显然的 \(O(tn)\) 的最段路 dp,然后发现 \(t\) 是 \(O(n)\) 的,证明考虑一条最短路路径外连四个点,寄了,然后做完了。
AT_arc201_d [ARC201D] Match, Mod, Minimize *2389
给你两个长度为 \(N\) 的数列 \(A=(A_1,A_2,\cdots,A_N),B=(B_1,B_2,\cdots,B_N)\) 和一个正整数 \(M\),你可以对 \(A\) 重新排序,求 \(\max_{i=1}^N((A_i+B_i)\bmod M)\) 的最小值。
\(N \leq 3 \times 10^5,M \leq 10^9,A_i,B_i<M\)。
比较智慧的题,但是孩子是笨蛋。
我们首先把所有 \(a\) 取负号,此时题目里面的柿子就变成了 \(\max_{i=1}^N((B_i-A_i)\bmod M)\) 的最小值。考察 \(\mathrm{max}\) 里面的值,若 \(B_i \geq A_i\) 就是 \(B_i-A_i\),否则是 \((B_i-M)-A_i\)。那么相当于我们要选一些 \(B_i\) 加 \(M\),使得能重新排列使得所有 \(B_i>A_i\),然后再对上面那个柿子来求。
首先考虑假设已经确定了加完 \(M\) 后的 \(B\) 数组,怎么来配对,显然是把 \(A,B\) 分别从小到大排序后配对。
那么我们考虑选哪些 \(B_i\) 加 \(M\),显然是尽量先加小的 \(B\),因为你考虑加完以后 \(B\) 排序后的什么形态,显然是没加的放前面,加了的放后面,并且这些加了的一定能配上 \(A\)(因为 \(A_i<M\),\(B_i+M \geq M\)),所以我们肯定是让这些加 \(M\) 的人尽量小,并且我们还发现这样能使得剩下的没有加 \(M\) 的整体最大,让和这些没有加 \(M\) 的 \(B\) 更容易能配上 \(A\),因此这个策略是最优的。
那么我们把 \(B\) 整体加 \(M\) 后往后复制一份,即构造 \(B'_i=B_{i-n}+m(n<i \leq 2n),B_i(1 \leq i \leq n)\)。显然 \(A\) 一定是跟 \(B'\) 的连续 \(n\) 个配,容易发现这连续 \(n\) 个越往后移动答案越大,因此直接二分然后 check 是否能配上即可。
AT_agc001_e [AGC001E] BBQ Hard
给定 \(n\) 对 \((a_i,b_i)\),求 \(\sum_{i=1}^n \sum_{j=i+1}^n comb(a_i+a_j+b_i+b_j,a_i+a_j)\)。
\(n \leq 2 \times 10^5,a_i,b_i \leq 2000\)。
秒秒组合意义。
直接做是 \(O(n^2)\) 的。
考虑这个组合柿的组合意义,可以认为是从 \((-a_i,-b_i)\) 走到 \((a_j,b_j)\) 的方案数。那么我们把所有起点放到网格图上,dp 一遍求出每个位置的 从某个起点出发到达该点的路径数,然后再每个终点做求和即可。
AT_agc001_f [AGC001F] Wide Swap
给定一个长度为 \(n\) 的排列 \(p\),每次你可以交换一对距离不小于 \(k\) 的满足值差绝对值为 \(1\) 的数,问最后字典序最小的排列是什么。
\(n \leq 5 \times 10^5\)。
首先取 \(p\) 的逆排列 \(q\),那么在 \(p\) 上的一次交换 \(p_i,p_j\) 就相当于在 \(q\) 上交换了 \(q_{p_i},q_{p_j}\)。
那么就可以把题目条件改写成可以交换 \(q\) 中相邻的满足差不小于 \(k\) 的数。然而注意到 \(q\) 的字典序相对大小并不能代表 \(p\) 的。在 \(p\) 中我们要尽量把小的数往前放,这个规则应用到 \(q\) 上应该改写成把大的尽量往后放。(注意,这两者意思并不一致,可以细细品味。)
于是类似于冒泡排序就可以做到 \(O(n^2)\),改成归并就可以做到一只 log。
具体怎么改?首先有最基础的归并框架 solve(l,r),先把 \([l,mid],[mid+1,r]\) 能换尽换,然后考虑内部交换的情况。考虑 \([mid+1,r]\) 的一个 \(x\) 什么时候可以先放,显然是它加 \(k\) 小于等于左边的数的后缀最小值,双指针维护两边现在要加的数即可。
AT_agc002_d [AGC002D] Stamp Rally
给定一张图,边有编号,输入时给出。有多组询问,每次询问两个点 \(x,y\) 和 \(z\),询问两点各走若干步,被走过的点数恰好为 \(z\) 时,走过的边的编号最大值最小能是多少。\(n,q \leq 10^5\)。
把编号当边权,建立重构树。询问的时候二分答案,即要看只能走 \(\leq mid\) 的边的话能到达的点的数量是否大于等于 \(z\),那么在重构树上把 \(x,y\) 网上跳一下就可以算出这个东西,然后做完了。
AT_agc002_e [AGC002E] Candy Piles
有 \(n\) 个数,两个人博弈,轮流做,要么让最大数减一,要么让所有非负数数减一,让所有数都变成 \(0\) 的人输,问先手输赢。\(n \leq 10^5\)。
注意到这个操作的形式,画出 \(\{a_i\}\) 的直方图,相当于每次可以砍掉最左边的一列(假设按照从大到小从左到右排列),或者砍掉最下面的一行。可以发现剩下的部分可以被描述为 某个点右上方的区域。即剩下的区域可以简记为这个点。而我们的操作其实就是每次可以让这个点向上或向右移动这个点。当点走到了直方图边界,那么就相当于输了。此时就变成了一个网格图上的博弈问题,用 \(dp\) 可以做到 \(O(\sum a_i)\)。直接优化看起来没有前途,然而我们可以找规律,可以发现对角线的状态都一样,而行列之间变化有奇偶性联系,所以直接看和边界的距离即可。
具体证明可以参考这个。
AT_agc002_f [AGC002F] Leftmost Ball
Snuke 喜欢彩色球。他共有 \(N\times K\) 个球,其中包含 \(N\) 种他最喜欢的颜色,每种颜色各有 \(K\) 个。颜色编号为 \(1\) 至 \(N\)。
他将所有球从左到右排成一行,顺序任意。然后,对于每种颜色,他会将该颜色最左侧的球重新涂为颜色 \(0\)(这是一种不同于原有 \(N\) 种颜色的新颜色)。
涂色完成后,球的颜色序列可能有多少种不同的排列方式?请将答案对 \(10^9+7\) 取模。
\(N,K \leq 2000\)。
奶龙决定以后不再自己写一遍简要题意。
你会发现你没有什么好的方法来判断两个颜色球序列做一遍题目说的事情以后一不一样,所以我们考虑直接对变换后的序列看,那么其实就变成了一个判定问题(考虑每一种情况,如果可行那么答案+1)。判定是可做的,我们把最终状态里每一种颜色的第一次出现视为右括号,白色球视为左括号(因为每个白色球可以匹配他右边的一个第一次出现的球),那么如果是合法串,就可以由某个原始序列经变换得到。
这个时候会想着去 dp 一手,考虑从前往后扫,但是你会发现这样你需要记录每个颜色当前用了几个球,这和暴力没啥区别啊。然而我们发现答案的合法与否只取决于白色球和每种颜色的第一个球的放置 相对位置,因此我们可以考虑 dp 状态表示:从前往后扫,当前放了 \(i\) 个白球,\(j\) 个第一颜色球,显然需要满足时时刻刻 \(i \geq j\)。我们钦定每次放置白色或第一颜色球的时候都放在当前的第一个空位上,这样就能保证我们 dp 是按照顺序进行的(不然的话如果不放在第一个空位上,后面一定会有一个第一颜色球或者白球放上面,那么顺序就乱了,我们 \(i \geq j\) 的限制是根据顺序来定义的,如果不按照这种方式来这个限制也无用了)。转移的时候放白球就是直接继承贡献,放颜色求因为还有 \(k-2\) 个非白球非第一颜色球可以放,就拿组合数算一下即可。
稍后把 agc003 的题加上,你妈的傻逼文化课。

浙公网安备 33010602011771号