Hey Gift:发迹

WC 之前真没什么能训的了。

愿好心态永远伴随着我。这次真的是为自己而战了。

Codeforces Global Round 31 (Div. 1 + Div. 2)

CF2180E

严肃做不起绿题中!猜不到,真的猜不到。

考虑直接把 \(l\oplus r\) 的最高位抽出来,因为更高的位是锁死的。随后我们发现在这一位上有两种东西:\([l,2^k)\)(这一位为 \(0\))和 \([2^k,r]\)(这一位为 \(1\))。

考虑 \(x\) 中这一位为 \(0\) 的情况。那么我们需要两边独立地自洽。为了方便,不妨把 \([2^k,r]\) 改写成 \([0,r-2^k]\)(实际上的 \(x\) 额外异或一个 \(2^k\))。那么这样就容易看出来了,不难证明我们只能取 \(r-2^k\) 的最末尾的一段 \(1\) 的子集。

那么现在回过去看 \([l,2^k)\)。不难发现如果一个数 \(x\) 可以使得 \([l,2^k)\) 自洽等价于让 \([0,l)\) 自洽。所以情况也是类似的。

考虑 \(x\) 中这一位为 \(1\),那么我们希望右边映射到左边,左边映射到右边。这首先需要两侧长度相同,不妨假设均为 \(L\),那么左侧即为 \([2^k-L,2^k)\),右侧即为 \([2^k,2^k+L)\Rightarrow[0,L)\)。考虑改写左边的范围,可以发现我们如果给 \(x\) 异或一个 \(2^k-1\) 就可以变成 \([0,L)\)。所以又变成了给 \([0,L)\) 异或一个数还在 \([0,L)\) 以内,那么这个就和前面一样了。

CF2180F1

还没看。

Codeforces Round ???

QOJ #663. Spanning Trees

简单构造。

答案上界显然是 \(\left\lfloor\frac{n}{2}\right\rfloor\),考虑怎么达到它。不妨经典地把完全图排在一圈上,容易手玩出来一个这样的构造:

image

做出前 \(k\) 个即可。

Jeremy Sp @Track. 4: Time to Heal

题单

打 * 的是自己解决的。感觉我比我想象中恢复得好啊,那不做 SB 题了。

*1706E Qpwoeirut and Vertices, 2300

一开始在想 dsu 和 odt 缝在一起,发现要写矩形取 min 和求矩形 max,这是困难的。

考虑最小的使得 \((a,b)\) 连通的 \(k\),由经典技巧容易发现这个就是最小生成树上 \(\max a\to b\)。所以我们直接把最小生成树抽出来,然后 Kruskal 重构,等价于求一个点权最大的点包含所有 \([l,r]\) 当中的点。

显然这个点就是 \([l,r]\) 虚树的根,所以我们直接找出 \([l,r]\) 中 dfs 序最小和最大的点,取它们的 LCA 即可。

1310B Double Elimination, 2500

要学会发现独立的子结构

这个题一眼看过去一点思路都没有。但可以发现这里面蕴含了一个简洁的最优子结构:

  • 整个比赛的结构树是固定的。这实际上是一个非常强的性质。由于我们按照编号直接分组,所以每场比赛的参赛者一定来自于之前某场比赛的胜利者和失败者,这是固定的,与实际谁赢了没有关系。

其实样例解释暗戳戳指出了这件事,但我没有发现,反倒因为这个按编号分组的问题很纠结。

但是这样我们还不能直接设计 dp。因为状态看上去具有后效性,前面某场比赛的结果对后面比赛是有影响的(如果不考虑后效性就会出现之前一场比赛的状态可能同时来自一个人的输和赢,但是两者只能存在一个,是互相影响的)。

乍一看没招了,实际上不是的!考虑每一场里面会自相影响的那些比赛,其实都可以压缩在一起。例如样例当中 \((f,j)\) 这两场比赛会互相影响,但它们的结果依赖且仅依赖于上一轮中 \((c,d,h)\) 这三场比赛的结果。

image

暂时不考虑需要存储多少信息。进一步不难发现在第 \(i\) 轮中,我们可以把每 \(2^i\) 个人产生的状态压在一起,而每 \(2^i\) 个人之间都是不产生互相影响的。于是就没有后效性了。

然后考虑往后递推需要多少信息,可以发现这样一个等价类里面其实只有胜者组赢家和失败组赢家对下一轮结果有影响,因为上一轮的胜者组输家已经合并到了上一轮的失败组赢家,而失败组赢家是真的没用。另外,显然赢家是谁也不重要。于是设 \(f_{i,j,0/1,0/1}\) 表示第 \(i\) 轮,\((j-1)\times 2^i\)\(j\times 2^i-1\)\(0\)-index)这些人的胜者组/败者组赢家是否是我喜爱的队伍,这种情况下的最大答案。

于是 \(f_{i,j,0/1,0/1}\gets f_{i-1,2j,0/1,0/1},f_{i-1,2j+1,0/1,0/1}\),合并这个状态只需要暴力枚举三场比赛的结果就可以了。讨论一下即可。需要注意最后一轮比赛的特殊性,我们递推到 \(f_{n}\),最后一步手动处理即可。

image

*1799F Halve or Subtract, 2700

我现在还能过 *2700 吗??科幻!

先给 \(a\) 按升序排序。显然整个东西的操作方式只有三种:

  • A. \(x\gets x-b\)
  • B. \(x\gets \left\lceil\frac{x}{2}\right\rceil\)
  • C. \(x\gets \left\lceil\frac{x}{2}\right\rceil-b\)

Lemma 1. 所有 C 方式一定聚集在一个后缀。
Proof. 考虑如果存在一个 C 方式不在后缀,那么容易分类讨论证明,把它和现在 C 后缀前面第一个非 C 的互换总是不劣的。通过一直这样交换,我们一定可以把 C 聚集在后缀。

于是枚举这个后缀,考虑怎么给前面分配。显然如果前面还能用的操作总数超过了序列长度,那么根据抽屉原理必然有一个要用 C 方式,所以是不合法的后缀。考虑对于合法的后缀,我们贪心地给每个元素分配用 A 还是用 B。

Lemma 2. 所有 A & B 方式也聚集在前面的一个后缀。
Proof. 仍然考虑把脱离后缀的挪到和后缀放在一起,是不劣的。

假设我们还有 \(L=k_1'+k_2'\) 个操作次数,于是我们只对前面的后 \(L\) 个元素进行操作即可,其中每个元素只允许使用恰好一种方式操作。显然,我们可以先把所有元素都用 B 方式操作,然后选择改变操作方式的代价最小的一部分撤销。就做完了。

*1334E Divisor Paths, 2200

考虑实际上每次是付出了 \(d(\frac{x}{p^i})\) 的代价使得 \(x\gets px,p\in\mathbb{P}\)。经过手玩可以发现从 \(1\) 开始变成任何数,无论使用何种方式乘出它的质因数分解都是相等代价的。

现在考虑任意 \(u,v\),不难发现把两边都变成 \(\gcd(u,v)\) 最小。

*1779F Xorcerer's Stones, 2500

考虑推平一棵奇数大小的子树,容易发现这完全不会影响整棵树的异或和。所以我们永远不会操作一棵奇数大小的子树,这个操作本身是没有效果的,对于后续利用它的操作来说它也是无效的。

考虑推平一棵偶数大小的子树,连续推两次之后,不难发现这会让整棵树的异或和异或上它的子树异或和。很明显异或相交的两棵子树没有意义,所以等价于在树上求一个反链,使得反链的子树异或和恰好为整棵树的异或和,并且反链中每个点的子树大小都是偶数。dp 即可。构造方案恶心死了。

*793D Presents in Bankopolis, 2100

简单的办法是设 \(f_{k,L,R,p}\) 表示走了 \(k\) 步,左右的限制为不能跨过 \(L,R\),当前位置为 \(p\) 的最小答案。直接朴素做是 \(\mathcal O(n^3m)\),无法通过。

考虑优化状态,不难发现 \(L,R\) 当中必然有一个是上一步走的那条边的端点,而 \(p\) 就是上一步走的那条边的端点,所以状态可以改为 \(f_{k,i,lim,L/R}\) 表示走了 \(k\) 步,上一步走的边是 \(i\)(所以现在在 \(v_i\)),其中 \(L/R\) 边界上是 \(u_i\),另一边边界是 \(lim\),这样就用 \(\mathcal O(n^2m)\) 的状态把所有状态都表示出来了。

转移考虑 mitm,先从 \(f\) 挂到 \(v_i\) 上,然后再枚举所有边,从 \(v_i\) 转移出去。转移时使用前缀和优化,复杂度即可做到 \(\mathcal O(n^4+n^2m)\)

*1063D Candies for Children, 2600

我这个做法细节多到令人发指啊。

不妨只考虑所有糖恰好分完的情况,最后一个人吃甜食且只分到一颗的情况是类似的。

我们设转了 \(C\) 圈,一共有 \(m\) 个人吃甜食,其中 \(l\to r\)(左右均包含)当中有 \(t\) 个人吃甜食,令 \(L\) 表示 \(l\to r\) 的人数,那么我们实际上得到了一个等式——

\[C(n+m)+L+t=k \]

不难发现一组 \(C,m,t\) 合法当且仅当满足以下条件:

  • \(C\le 0\)
  • \(\max(0,L-n-m)\le t\le \min(L,m)\)

考虑对 \(C,n+m\) 根号分治:

  • 枚举 \(C\),那么可以得到 \(Cm+t=k-L\)。我们可以取到最大的 \(m=\left\lfloor\frac{k-L}{C}\right\rfloor\),并获得一个 \(t\)。但有可能这个 \(t\) 并不能满足下界,所以我们每次 \(m\gets m-1,t\gets t+C\),把 \(t\) 调整到下界再做判定。
  • 枚举 \(m\),那么可以得到 \((n+m)C+t=k-L\)。这里我们直接取最大的 \(C\) 然后判定就可以了,不需要调整。

对于最后一个人吃甜食且只分到一颗的情况,我们假设现在多了一颗糖,并把 \(t\) 的下界缩小为 \(t\ge 1\) 即可规约到上述情况。

*617E XOR and Favorite Number, 2200

莫队板子,不知道为啥想了半天。分块也是可以做的。

1028E Restore Array, 2400

为啥不会做构造题啊,睡眠中。

考虑一个简单的想法是,我们让 \(a_i>a_{i+1}\land a_i-a_{i+1}=b_i\),这样看上去就可以满足 \(b_i=a_i\bmod a_{i+1}\) 了。一个美妙的办法是 \(a_i=\sum\limits_{j=i}^n b_j\)\(b_n=a_n\bmod a_1\) 也由于 \(a_n<a_1\land a_n=b_n\) 恰好满足了。

然而显然不行。如果 \(a_i\ge 2a_{i+1}\iff b_i\ge a_{i+1}\) 我们就没办法取到这个 \(b_i\) 了。我们充分发扬人类智慧,把 \(\max b\) 挪到 \(b_n\) 去,然后只要 \(b_{n-1}\ne b_n\land b_n>0\) 这个条件就可以总是满足了。

\(b_n=0\) 的情况是平凡的。

对于 \(b_{n-1}=b_n\) 的情况,显然除了整个序列都相等以外我们一定能找到一个满足 \(b_{n-1}\ne b_n\) 的最大值。不难反证这种情况除了 \(b_n=0\) 都无解。

还有一点小问题,注意到如果 \(b_1=b_2=\cdots=b_{n-1}=0\) 那么 \(a_1=a_n\)\(b_n\) 就无法满足了。但这是可以简单解决的,我们的做法只是建立在前面大于后面的基础上,所以可以往上面随意地加东西。由于我们不能给 \(b_n\) 加,所以我们只能加上 \(b_n\) 的倍数使得 \(n-1\) 位置不会出错。

264D Colorful Stones, 2500

难得离谱啊,AGC 吧??

看完题感觉有零个头绪,于是首先猜一个结论,钦定 \(S\) 里面走到 \(i\),那么所有可达的 \(j\) 在一个区间 \([L_i,R_i]\) 里,这个区间可以双指针出来。交上去倒闭,说明所有可达的 \(j\) 不一定在一个区间里。

显然从 \(i\) 处新扩展出去的一定可达,所以我们只管 \([L_{i-1},R_{i-1}]\) 里面哪些从可达变成了不可达。先不管 \(j=L_{i-1}\),不妨考虑什么东西会导致 \((i-1,j-1),(i-1,j)\) 都可达但是 \((i,j)\) 不可达。

显然可以排除 \(S_{i-1}=T_{j-1}\)\(S_{i-1}\ne T_j\)。于是只需讨论 \(S_i\) 是哪个字符。不难发现倒闭的形态其实是:

   i-1 i    j-1 j
...a   b
............b   a

恰巧这种情况即便 \((i,j-1)\) 可达也没救,所以此时我们无论如何都无法扩展到 \((i,j)\)

对于 \(j=L_{i-1}\) 处,不难发现它是平凡的。因为只有 \((i-1,j)\) 维持它的存在,所以仍然是一个朴素的双指针——如果 \(S_i=L\),则 \(L\gets L+1\)

于是问题开始变得清晰起来。我们只需要沿用双指针的办法算出 \([L_x,R_x]\),然后计算 \([L_x,R_{x-1}]\) 当中有多少个 \(\overline{S_iS_{i-1}}\) 把它们减去即可。使用前缀和优化,复杂度 \(\mathcal O(n)\)

这道题还可以通过网格图刻画来得出解法。对于这一类双串 / 双序列的问题,网格图是非常有力的刻画手段。

*402E Strictly Positive Matrix, 2200

根据著名转化矩阵乘法就是传递闭包,建立有向图跑一遍 tarjan 即可。

1695E Ambiguous Dominoes, 2700

结论假了真难绷。以后能不能多手玩一会。

考虑一下这个变化解到底是在干什么。对多米诺骨牌自然地想到连边,于是我们把连的边画出来,发现实际上是一堆偶环,两种解本质上是偶环的两种匹配方式。

image

既然是偶环,实际上我们一定可以直接摊平到两行上。那么构造就容易了。

现在考虑怎么把这个偶环弄出来。我们希望某条边在经过奇数次之后再次出现,以达到一个奇偶性不同从而出现在不用匹配中的效果。这种诡异图论构造容易想到用欧拉回路来解决。

不难发现如果我们把同一条边的两次出现拆成两条边,那么所有点都是偶度点,所以一定存在欧拉回路。trickily,我们考虑对欧拉回路黑白染色达到构造出两种匹配交替的环的效果。在此基础上希望一条边的两个分身恰好具有两种不同颜色是简单的,当我们经过一条边第一次之后,我们下一次立即走它的分身即可。不过由于 \(x\to y\)\(y\to x\) 总是一起加入,所以经过一些感受 / 归纳证明可以发现我们直接按照邻接表顺序访问就好了,它和它的分身之前总是会有偶数条边。

综上所述不难得出无解的情况有且仅有一种:一个连通块只有一条边。因为它无法变为偶环。

之后就是 implementation 了。

*1737E Ela Goes Hiking, 2500

写这篇做题记录的时候觉得身上有蚂蚁在爬。

为啥充要条件找半天找不对。

首先容易发现,最左侧的蚂蚁左右都等价于右,最右侧的蚂蚁左右都等价于左,不妨直接钦定最左侧蚂蚁向右,最右侧蚂蚁向左。

然后我们发现,从初始状态开始,所有的 \(\to\to\to\cdots \to\gets\) 这样的段会被合并到那只 \(\gets\) 的蚂蚁上。这意味着一只蚂蚁要想活到最后必须向左。

合并结束之后,每只蚂蚁都将向左(实际上是只有向左的蚂蚁还活着),大小为自己所在那个极长段的大小,不妨记作 \(\{a\}\)

接下来,我们钦定活到最后的蚂蚁左侧的蚂蚁会全部合并在一起向右冲向我们。因此我们必须满足 \(a_i\ge\sum\limits_{j=1}^{i-1}a_j\)。回到原来的样子就是,假设极长段长度为 \(L\),钦定第 \(i\) 只蚂蚁活到最后,那么必须有 \(i-L\le L\Rightarrow i\le 2L\)

进一步我们发现,最终活下来的蚂蚁就是所有蚂蚁中最后一个满足 \(i\le 2L\) 的蚂蚁。

不妨 dp 它。\(f_i\) 表示只考虑这只蚂蚁后方的蚂蚁的方向,并且这只蚂蚁后方都没有蚂蚁满足 \(i\le 2L\) 的方案数。显然钦定式地容斥转移:

\[f_i\gets 2^{n-i}-\sum\limits_{j-i\ge \left\lceil\frac{i}{2}\right\rceil}^{n} f_j2^{j-i-\left\lceil\frac{j}{2}\right\rceil} \]

这个后面明显可以前缀和优化。

最后计算答案我们直接钦定这只蚂蚁的段长 \(L\ge \left\lceil\frac{i}{2}\right\rceil\),前面的任取即可。

Jeremy Sp @Track. 5: Mixed and Recovery

题单

先暂时放弃了 *2700,做一些比较新的 *2400 到 *2600 的题,让自己能够充分思考但又不至于太痛苦。

1903F Babysitting, 2500

被 trick 击杀了。遇到这种满足性,选一个就不允许另一个的题目,要考虑 2-SAT 的可能性。感觉没见过点覆盖和 2-SAT 套路的人很难想到啊。

考虑二分答案,那么压力给到 check,我们需要鉴定有没有一个合法的点覆盖。

点覆盖是一个具有 2-SAT 性质的结构。考虑一条边的两端 \(u,v\),点覆盖要求 \(\neg u\Rightarrow v,\neg v\Rightarrow u\),别的不管。于是不难发现这个题的 check 实际上就是一个 2-SAT,只是我们要加上如果选择了点 \(u\),那么要推到所有满足 \(|u-v|< mid\) 的点 \(v\) 都不允许选。

于是线段树优化建图即可。这个题的每个命题的逆否都是本身,所以还算比较方便。

*1493E Enormous XOR, 2600

一个愚蠢的方法。

根据知名结论,令 \(f(x)\) 表示 \(1\)\(x\) 的异或和,那么:

\[f(x)=\begin{cases} n,&n\equiv 0\pmod 4\\ 1,&n\equiv 1\pmod 4\\ n+1,&n\equiv 2\pmod 4\\ 0,&n\equiv 3\pmod 4 \end{cases} \]

所以我们把 \(x\)\(y\) 的异或和转化成 \(f(x-1)\oplus f(y)\)

首先不考虑前 \(n-2\) 位相差 \(1\) 的极端平凡情况,这部分暴力即可。于是四种可能性我们都能取到。

先考虑偶数 xor 起来。令 \(l',r'\)\(l,r\) 的前 \(n-2\) 位。在确保 \(r'-l'>1\) 的情况下,我们容易分类讨论发现我们总是可以在让前 \(n-2\) 位取到 \(l'\le x,y\le r'\) 的最大 \(x\oplus y\)(从 \(\operatorname{highbit}(l'\oplus r')\) 开始全是 \(1\))的同时,后两位各取一个 \(00\)\(10\)。所以这部分产生的答案就是一个 \(\operatorname{highbit}(l'\oplus r')+2\) 长度的全 \(1\) 串。

然后考虑用到奇数。显然我们总是可以获得 \(r'+11\) 或者 \(r'+01\)\(+\) 表示字符串拼接),这就是 \(r\)\(1\) 异或或者 \(r\) 本身的产物。其他使用奇数的办法不可能比这些更优,所以把答案和它取 lexicographically max 即可。

这个题正确的做法是,首先注意到 \(2i\oplus (2i+1)=1\),然后简单讨论:

  • \(l,r\) 第一位不相同,那么最大值只能是 \(2^n-1\) 了,取 \(2^{n-1}-1\)\(2^{n-1}\) 即可。
  • \(l,r\) 第一位相同,我们要把这个第一位留下来,那就要选奇数个数。我们选择 \([l',r']\) 这样一串数,由于上面说的每一对奇数偶数都消掉了,所以当 \(r'\) 是奇数的时候,这一段的异或和无法大于 \(r'\);当 \(r'\) 是偶数的时候,当且仅当可以使得 \(r'-l'+1=3\) 时这一段的异或和取到 \(r'+1\)。所以回到原来,当 \(r-l+1\ge 3\) 时答案是 \(r+1\),其余时候答案是 \(r\)

*1936C Pokémon Arena, 2400

手玩感受一下会发现下面的性质:

Lemma 0. 每种属性内部,至多给一个人加一次。
Proof.
加多次者,显然全部调整到最后加的那个人头上不劣。

Lemma 1. 一个人想要击败另一个人必然使用的是实力悬殊最近的那种属性。
Proof.
唯一的顾虑在于这样击败了之后是否会影响到之后这个人被其他人击败,显然是不影响的,因为另外一个人就不会选择用这个属性来击败它:如果比原来的它更大,我们无需经过它就可以直接击败当前的擂主,并且对属性的值是不增加的;如果比原来的它更小,根据 Lemma 0,我们要么直接加在这个击败它的人头上,要么就不存在这种人。

不妨大胆猜测不考虑属性的增加,认为 \(i\) 击败 \(j\) 需要的代价是 \(c_i+\max(0,\min a_{j,k}-a_{i,k})\) 是不合法不优的,我们直接连边 \(i\to j\) 建图跑最短路就能获得 \(\mathcal O(n^2m)\) 的算法。也容易发现这确实是对的,在整个过程中两次通过同一个属性是不优的,经过同一个人两次也是不优的,总之所有不合法的可能性都不够优,最终最小的只会是答案。

考虑优化建图。不难发现我们实际上可以把每种属性单独列出来按升序排序拉成一条链,这样从 \(i\to i+1\) 的边权为 \(a_{i+1,j}-a_{i,j}\)\(i+1\to i\) 的边权为 \(0\),就可以用一条路径表示用一种属性打败他人的边权了(差分优化建图)。对于每种属性拉一条链之后,链之间只允许在同编号点之间切换——这意味着利用这个人完成一次击败,产生 \(c_i\) 的代价。于是对每个人开一个虚点即可,链向虚点连边权 \(c_i\) 的边,虚点向链连边权为 \(0\) 的边。最后我们要求的就是从 \(1\) 的虚点走到 \(n\) 的虚点的最短路。

总共 \(nm+n\) 个点,形态类似网格图所以边数也是 \(\mathcal O(nm)\) 的,用 Dij 跑最短路,复杂度 \(\mathcal O(nm\log nm)\)

1558D Top-Notch Insertions, 2600

太难了。找充要条件太难了。主播做这题的时候找错了,看题解无法理解,研究为什么错的时候彻底明白了这个充要条件。

手玩可以发现,交换产生的结果是让整个序列变成原来序列的一个置换,一种交换方式一一对应了一种合理的置换。不妨考虑数排序之后的序列,要搞清楚发生交换对最终序列产生的限制。

首先由于最终是不降的,我们有 \(a_{i}\le a_{i+1}\)。而交换的限制在于,发生一次从 \(x\)\(y\) 的交换意味着此时 \(x\) 要严格小于它后面那个数 \(y\)。需要注意的是,我们需要对小于号的数量进行去重,因为有可能现在是 \(a_1<a_2\),之后把 \(a_3\) 插到了中间,于是我们只需要 \(a_3<a_2\)\(a_1\)\(a_2\) 的关系还是得到了满足,并且看小于号仍然只有 \(a_2\) 算数。换句话说,我们按照元素计算小于号的数量。

在确定小于号的数量之后显然就是一个插板法了。

考虑怎么确定小于号的数量。需要支持插入,那肯定可以平衡树,但考虑规避平衡树。我们不妨时光倒流干掉插入,假设整个序列已经插入完毕了,那么我们每次就是在删去第 \(y_i\) 大的数并给第 \(y_i+1\) 大的数上标记。线段树上二分即可。

然后比较 dirty 的是没保证 \(\sum n\)。所以清空线段树的方式是把所有操作存下来每次还原到初始态。

*2081B Balancing, 2500

我何德何能能通过 *2500 greedy 啊?

先搞清楚最后一个样例是怎么回事。你发现它本质上干了这么一件事:

image

也就是说,我们把原序列分成若干个递增段,那么我们实际上可以每次选中两段,保持它们中间的段的形态不变,让它们合并到两头的段里去。这样每次会减少 \(2\) 个递增段,所以我们得到一个答案上界 \(\left\lceil\frac{c}{2}\right\rceil\),其中 \(c\) 表示段数。

然后你发现奇数的时候有一种很阴的办法会让答案恰好少 \(1\)-2 4 5 2 虽然有 \(3\) 段,但是可以把 4 5 卡到中间去。考虑推广到很多段,不难发现在合并过程中第一段和最后一段本身是无法改变的,但我们可以贪心地让第一段和最后一段在合并过程中加入自身的那些段的斜率都为 \(1\),于是只需检查 \(a_{l_1}\)\(a_{n-l_c+1}\) 之间能否塞下一个公差为 \(1\) 的等差数列即可。

1583F Defender of Childhood Dreams, 2500

但是我为啥连 \(k=2\) 的正确构造办法也想不到啊?一直以为是 \(\left\lceil\frac{n}{2}\right\rceil\) 想了好久,该加训分治和递归了。

先考虑怎么构造 \(k=2\)。容易想到把点分成左半边和右半边,然后会发现两部分内部是一个子问题,我们大胆猜测两块之间用一种全新的颜色连接,向下就直接递归。显然这是一个正确的办法,我们也会这么去猜:

Mentally Proof.
假设我们使用了一种存在过的颜色填充中间,那么右侧每个点都会少一种颜色可以向外使用。我们知道两侧是子问题并且都已经最小化,所以让右侧每个点少一种可以向外使用的颜色必然会导致某个点无色可用,与其在那里添加一种新的颜色不如让两块之间用一种新颜色连接。

我们不难将这个构造推广,把点分成 \(k\) 个子问题,块之间用一种全新的颜色连接。不难发现这些块之间最长的这种颜色的路径不会超过 \(k-1\)。递归下去即可。直接朴素实现是 \(\mathcal O(n^2\log n)\) 的。

Seriously Proof.
不妨归纳证明。假设用 \(c\) 个颜色最多能使 \(k^c\) 个点的图满足要求。显然对 \(c=0\) 成立。下面证明用 \(c+1\) 个颜色无法取到 \(k^{c+1}+1\)。考虑此时删去任一种颜色的边,由于 \(c\) 个颜色至多只能使 \(k^c\) 个点的图满足要求,所以必须分成至少 \(k+1\) 个连通块,而连接这些连通块必须用到这种颜色的边,于是会出现长度为 \(k\) 的路径,故无法取到 \(k^{c+1}+1\)。而\(k^c\) 已经被我们构造性取得。

*1834F Typewriter, 2500

不难感受到答案就是 \(\sum[a_i<i]\)。首先这个肯定是答案下界,然后我们对于每个置换环单独拎出来,每次从这个置换环的最靠前的那个点开始做,然后最后回到最靠前的点即可。这样做之后显然每个置换环的操作次数都达到了下界,我们只需按照最靠前的点给置换环排序就可以省去切换置换环时的归零操作,所以这就是整体的下界。

考虑如何维护。不难发现询问只有 \(n\) 种:序列正反和左移长度。所以可以全部预处理出来。我不幸携带了 log,实际上可以做到 \(\mathcal O(n+q)\):每个点的贡献给到一个环上的区间的左移偏移量,差分和前缀和即可。

*1859E Maximum Monogonosity, 2500

难绷,我以为是 wqs 二分或者决策单调性,结果是我校传统艺能拆绝对值。

这个绝对值很恶心,我们直接拆开,令 \(f_i\gets a_i+b_i,g_i\gets a_i-b_i\),那么实际上一个区间 \([l,r]\) 的贡献是:

\[\max(-g_l-g_r,f_r-f_l,f_l-f_r,g_l+g_r) \]

考虑这种划分不相交线段的 dp 有两种写法,一种是一次性转移一个区间,\(f_i\) 表示 dp 完前缀 \(i\),最后一个区间的右端点是 \(i\) 的方案,这种方式有复杂度瓶颈,难以解决本题;另一种是一个一个往后 append,显然这里我们应该使用第二种,贡献形式可以通过差分做到一边 append 一边产生。

不妨设 \(f_{i,j,0/1,0/1/2/3}\) 表示当前 dp 完前缀 \(i\),已有的区间长度为 \(j\),当前是否在一个打开的区间当中,如果在的话,钦定这个区间的贡献形式是哪一种。不合法不优保证了它的正确性。直接暴力转移即可做到 \(\mathcal O(n^2)\)

*1739E Cleaning Robot, 2400

考虑随着这个机器人的移动来 dp 格子。不难发现唯一一种导致相同距离的情况形如:

image

考虑到遇到这种情况我们需要对格子进行操作,在当前这一步(有可能消掉的是下面的格子就不用走下去了)和未来的一步以内具有后效性,所以我们不妨设计状态 \(f_{i,r,mask}\) 表示走到了第 \(r\) 行第 \(i\) 列,\(i\)\(i+1\) 列的格子状态为 \(mask\),前 \(i-1\) 列都已经处理完毕的最大染色格子数。

因为从染色格子走到染色格子都是沿着最短距离走的,但我们只能一步一步挪过去,为了避免产生不必要的距离增加,我们在转移时不允许在同一列上移动,除非必须要清理同一列上的另一个格子。据此,转移只包括以下几种:

  • \((r,i)\) 走到 \((r,i+1)\),即向后一列。
  • 考虑清理 \((\neg r,i)\) 上的格子,即走向这一列上另外一格没有清理的格子。
  • 不移动,处理矛盾问题。保持在 \((r,i)\),但是周围和自己距离相等的格子要清除掉一个。

不难发现对于同一个 \(f_{i,r}\) 总是在减少格子数量,所以外层 \(i:1\to n\),内层按照 \(mask\) 倒序转移即可。卡空间需要滚动数组。

*1838E Count Supersequences, 2500

?这题被我 \(3\) 分钟秒了,题解在干什么,评分在干什么?

考虑容斥,我们计算有多少种序列 \(b\) 里面不包含任何一个 \(a\) 作为子序列。不妨考虑 \(a\)\(b\) 中的匹配过程,我们钦定它贪心地匹配了前 \(i\) 位(\(i\in[0,n)\)),然后考虑再把 \(m-i\) 个数插入到其中来构成合法的 \(b\)

由于我们钦定了是贪心地匹配,所以我们实际上要求插入的这些数满足如果在 \(a_i\)\(a_{i+1}\) 之间则不能出现 \(a_{i+1}\),否则会提前产生匹配,导致和另外一种匹配数相等的情况算重。换句话说,这个钦定的作用是把有多种匹配 \(a\) 的前缀 \(i\) 的方式的 \(b\) 按在最靠前那种方式上计数。进一步可以发现这实际上是在要求那 \(m-i\) 个插入的数每个数都少了一种可能性,所以答案就是:

\[\sum\limits_{i=0}^{n-1} {m\choose i}(k-1)^{m-i} \]

由于 \(m\le 10^9\),动态计算 \(m\choose i\) 即可。时间复杂度 \(\mathcal O(n\log P)\),瓶颈在于求逆元。

1854C Expected Destruction, 2500

学会把贡献摊开到独立的东西上。学拆贡献这种技巧真的是一个非常非常痛苦但是必须去积累去学的过程。还有就是期望线性性真的好难啊。

先考虑把这个东西刻画的漂亮一点。直接尝试计算答案较为困难,不难发现如果不允许合并,答案将是确定的 \(\sum m+1-S_i\),而两个元素在 \(t\) 处合并会导致答案减小 \(m+1-t\)。于是不妨补集转化,计算所有情况下减少时间的期望。

考虑怎么看待合并产生的贡献。我们可以认为合并不会改变元素之间的相对顺序,进一步地,不妨认为已经合并的元素只是堆在一起了而已,实际上是一个区间 \([l,r]\),所以当两个元素 \([l_1,r_1],[l_2,r_2]\) 合并,我们其实可以理解成 \([r_1,l_2]\) 合并在一起了。在这种理解下,我们的单次操作实际上是把 \(i,i+1\) 合并在一起最后逐渐合成一整段,并且所有的合并实际上都是独立的:对于 \(i,i+1\) 合并的位置只要求 \(\ge S_{i+1}\),块之间并没有影响。

所以我们可以独立下去,考虑计算一段合并产生的贡献。不妨 dp \(f_{i,j}\) 表示左边移动到 \(i\),右边移动到 \(j\) 的概率,初始的时候 \(f_{S_i,S_{i+1}}=1\),我们最终对答案减去所有 \(f_{t,t}(m+1-t)\) 即可。转移非常深刻:

\[f_{x,y}\gets \frac{1}{2}(f_{x-1,y}+f_{x,y-1}) \]

可以这样想:操作其他块对状态的影响是无意义的,所以到最后还是 \(\frac{1}{2}\) 的概率在里面二选一。代数上来说,假设当前有 \(s\) 个元素,那么它就是下面式子的移项:

\[f_{x,y}\gets \frac{s-2}{s}f_{x,y}+\frac{1}{s}f_{x,y-1}+\frac{1}{s}f_{x-1,y} \]

仍然是因为操作其他 \(s-2\) 个元素对这两个元素的位置没有影响。

写代码时需要注意 \(x>y\)\(f_{x,y}\) 不应有值。

直接这样做可以做到 \(\mathcal O(nm^2)\)。进一步地,由于所有情况的最终贡献形式和 dp 方式都相同,我们可以直接放在一起只做一次 dp,这样就可以做到 \(\mathcal O(m^2)\) 了。

我记得联赛之前打洛谷的比赛的时候也有个题这样,我理解不了递推式的系数。最后被车人指出是移项得到的结果。写完这篇做题记录之后我感觉这并不是期望线性性的结果,那样想把问题想得太需要脑筋。实际上就是因为问题支持把一个小过程从大过程里独立出来,所以会出现操作作用到小过程以外的地方,对小过程没有影响但是确实是做了,此时就会出现小过程在相同状态内部转移,产生神秘的系数。

数贡献的时候一定要想尽办法把贡献摊开或者找到更简单的计算方式。正着不好算就倒着或者反着算。这题就是看似元素合并很有说法,试图维护合并就会很难记录状态和对应的概率,实际上换一种理解角度却可以直接独立下去,概率也可以简单计算了。

哎,这种到底能咋练呢。

2026E Best Subsequence, 2500

气笑了。转化出了建图,没想到最大权闭合子图居然是能做的。这种选择一个就必须选择另外的一些显然都是这个模型。

不难发现这题的形式是选了一个东西就要选另外的。如果我选择了一个数,那么就必须要把若干个数位都选进来。

考虑数往数位连边,不难发现如果设置数的权值为 \(1\),数位的权值为 \(-1\),那么就是最大权闭合子图,这是可以用 flow 完成的

最大权闭合子图太麻烦了,考虑能不能不用它。不妨补集转化一下,选择一个数集然后抠掉被任意一个它当中的元素指到的数位,可以看成是抠掉 \(60\) 减去不被它指到的数位。然后不难发现一个数集连同右侧的数位集的补集是一个独立集,所以答案就是最大独立集减 \(60\)

这是二分图的最大独立集,根据 Konig 定理,只需要用 Dinic 跑一个最大匹配出来即可。

*1513F Swapping Problem, 2500

只会写暴力了,咋办。

考虑选择一对 \(i,j\) 对答案产生的 \(\Delta=-|a_i-b_i|-|a_j-b_j|+|a_i-b_j|+|a_j-b_i|\)

考虑分治,考虑怎么算 \(i\) 在左边 \(j\) 在右边对答案的最小 \(\Delta\)。最后两个绝对值依赖于 \(a_i,b_j\) 的大小关系和 \(a_j,b_i\) 的大小关系,不妨先讨论 \(a_i\)\(b_j\) 的大小关系。不难想到类似 cdq 分治,我们给左边按照 \(a\) 排序,右边按照 \(b\) 排序,这样我们只需双指针保证 \(a_i\ge b_j\)\(a_i\le b_j\)

考虑 \(a_j,b_i\) 的大小关系,也类似 cdq 分治地用树状数组进行讨论。

贡献拆开之后只需写两个树状数组进行前后缀 \(\min\) 即可。实现时注意树状数组的清空复杂度。总时间复杂度 \(\mathcal O(n\log ^2n)\)

真正长脑子的做法是这样的:

Lemma. 不会交换两个 \(a_i<b_i,a_j<b_j\)\(i,j\)。(翻过来同理)
Proof. 转化到数轴上观察 \([a_i,b_i],[a_j,b_j]\) 两个区间,不难发现交换之后的区间覆盖长度总是不短于交换之前。

所以我们只会交换 \(a_i<b_i\)\(a_j>b_j\) 的两个位置。可以发现如果产生这样的交换,那么对答案的减小量恰好是两倍的区间交。所以我们把两种区间放在两个集合里,只需求在两个集合各取一个区间产生的最大区间交,直接排序扫描线即可。时间复杂度 \(\mathcal O(n\log n)\)

注意这个是可以规避数据结构的。我们考虑按照 \(r\) 排序倒着扫,那么可以确定贡献的右端点,而最小化左端点只需直接在扫的过程中维护左端点最小值即可。

*1912H Hypercatapult Commute, 2400

显然题目要求我们构造一棵内向基环树,其中每个点都可以沿着出边到达自己想去的点集,然后输出它的拓扑序就可以完成任务了。然而值得注意的是,这里的拓扑序显然需要断掉一条边,而断边的后果则是有一部分点最终只能绕回起点 \(s\),而无法绕回自己的前驱。形式化地,每个点都只能走到自己的后继中不经过 \(s\) 的那部分。

不难发现构造内向基环树不如构造环,我们可以把每个环点上的树按照拓扑序塞到环里去。

紧接着不难发现,如果不考虑所有点都能走回 \(s\) 的话,我们可以直接将 \(s\) 这个点删除。那么它本质上就是一条链

显然只有 DAG 的情形才能使得我们把拓扑序排成一条链之后每个点都能到达自己的全部后继。只要还有环就一定需要返回。

于是不难得出结论:我们找到一个点 \(s\) 作为起点,这个点需要满足删除它的所有入边之后整个图变成了一个 DAG。也即图上所有环都需要经过它。找到这个点之后我们只需删去它的入边,将它作为第一个进入队列的点,然后按照 DAG 拓扑序构造链,最后把链尾指回 \(s\) 即可。

考虑怎么找到 \(s\)。由于数据范围较小,暴力删边之后进行拓扑排序即可。

注意这个题图不连通,所以每个连通块都要干这么个事情。为了让使用的边数最少,对于 DAG 的图还需要注意可以少用一条边。

*2060G Bugged Sort, 2400

不难发现这个操作等价于交换 \(i,j\) 上的两个数对并进行翻转。经过一定时间的折磨之后我发现我犯蠢了——实际上我们可以直接确定最终数对的顺序。

于是先对数对进行排序,并排除掉无法完成排序的情况。现在只需考虑能否产生对应的翻转。

不难发现任意翻转并不会改变整个序列的是否翻转异或和。这引导我们猜测只要最终翻转的数对的数量不是奇数就有解。事实上也的确如此。

Proof.
鸽了。

于是直接计算排序后的数对数组中需要翻转的数对数量即可。需要注意可能存在一段独立的数对,比如:

1 2 5 7 8  11
3 4 6 9 10 12

\([1,2],[3,5],[6,6]\) 的数对都是互相独立的,我们可以把这一个区间中的数对整体翻过来,不影响排序的合法性。于是还需 check 是否存在长度为奇数的独立区间,只要存在我们一定可以把数量控制到偶数。如果不存在则这些独立区间不影响奇偶性,直接数就好了。

Squarepoint Challenge (Codeforces Round 1055, Div. 1 + Div. 2)

别的不知道,这是真难绷。

C. Triple Removal

我做不起的黄题!这个也太难猜了吧。

D. Division Versus Addition

这是啥东西。

F. Triple Attack

考虑等价于选一个子序列出来使得任意 \(a_i-a_{i-2}>z\)。不难想到奇数和偶数位是独立的,我们可以放置两个指针 \(l,l+1\),从这两个位置开始往后贪心地跳(尽量选择最靠前的合法位置)来分别选择自己的子序列。

然而这两个子序列可能会想选相同的位置 \(i\)。贪心地,此时的调整方法显然是让其中一个指针落在 \(i\),另一个落在 \(i+1\)。注意到这递归到了一个相同的子问题,相当于查询 \([i,r]\)

显然应该使用倍增解决这个问题。\(f_{i,j}\) 表示从 \(i,i+1\) 起跳,经过 \(2^j\) 段跳跃之后叠在哪个位置上。再顺便维护一个数组 \(g\) 表示每段跳跃的长度和即可。

考虑怎么计算一段跳跃的信息。套路地,我们只需给 \(i\to next(i)\) 连边得到一棵树,那么重叠点就是 LCA,这一段跳跃的长度就是路径长度。

查询时从 \(l,l+1\) 起跳,倍增到 \(<r\) 的最后一段跳跃。因为最后一段跳跃可能取不满,单独拿出来在 \(i\to next(i)\) 那棵树上再倍增一次即可。

G. Query Jungle

G <<< F。

不难发现题意是要数整棵树上黑点构成的反链大小 / 虚树的叶子数量。那么算反链大小就可以一眼 ddp 板子,直接剽过来改改可能还是能写完的。不过我们考虑一下高明的办法。

考虑 ddp 的坏处是我们要把答案自下而上垒上去,点之间不够独立。

所以不妨尝试考虑一个点是虚树叶子的充要条件。可以发现,如果维护 \(nxt_i\) 表示某个点在 dfs 序上的下一个黑点,那么我们只需求出 \(dfn_{nxt_i}>dfn_i+siz_i-1\) 的黑点 \(i\) 的数量。这个信息明显非常容易结合,我们在线段树上维护 \([l,r]\) 中的答案,以及 \(dfn\) 最左侧黑点和 \(dfn\) 最右侧黑点即可。同时维护翻转是容易的,对于所有白点维护相同的信息即可。

Jeremy Sp @Track. 6: Constructive Algorithms and Math

题单,tags: constructive algorithms, greedy, math, ~2400

我的人生都被神秘思维题毁了。

1866M. Mighty Rock Tower, 2400

无穷期望无法战胜啊!

考虑这个石头必须一层一层垒上去,所以套路地,我们设 \(f_i\) 表示使得 \(i-1\to i\),并且不会从 \(i\) 坠落可以继续向上垒的期望步数。把所有 \(f\) 加起来就是答案。

然而搭上去是有可能坠机的,此时需要消耗其他步数把它垒回来。考虑对是否坠落到最底部进行讨论,不难得出递推式:

\[f_i\gets 1+\sum\limits_{j=1}^{i-1} P_i^{j}(1-P_i)\sum\limits_{k=i-j+1}^i f_k+P_i^i\sum\limits_{j=1}^if_j \]

这个东西怎么理解 突然感觉自己并不能很好地理解“期望步数”这个状态。

考虑期望的本质:所有事件的概率乘权值。这里的意思其实是,所有从 \(i-1\) 出发,不管中间发生了什么事情,最后总之是走到 \(i\) 的路径的长度乘上它对应的概率。

dp 的本质就是加法原理。我们考虑按照第一步分类进行 dp。有两种可能性:走到 \(i\) 坠落或者不坠落。对于不坠落和坠落的情况在 \(f_{i-1}\to f_{i}\) 都必然需要消耗一步,所以可以把 \(1\) 提取出来。这样不坠落的情况就处理完了,剩下只需考虑走到 \(i\) 坠落产生的额外步数。

坠落产生的额外步数也只需考虑第一次走回来(走回来之后就回到了 \(f_i\),所以不用再往后考虑了,直接使用 \(f_i\) 即可,这其实是在递归子问题)。其它中途遇到的波折被蕴含在前面的 \(f\) 状态中,所以我们直接求和即可。

考虑如何优化。先把 \(f_i\) 的项挪过去,然后不难想到前缀和手法:

\[\begin{aligned} (1-P_i^i-(1-P_i)\sum\limits_{j=1}^{i-1} P_i^{j})f_i&\gets 1+(1-P_i)\sum\limits_{j=1}^{i-1} P_i^{j}\sum\limits_{k=i-j+1}^{i-1} f_k+P_i^i\sum\limits_{j=1}^{i-1}f_j\\ (1-P_i)f_i&\gets 1+(1-P_i)\sum\limits_{j=1}^{i-1} P_i^{j}(S_{i-1}-S_{i-j})+P_i^iS_{i-1}\\ (1-P_i)f_i&\gets 1-(1-P_i)\sum\limits_{j=1}^{i-1} P_i^{j}S_{i-j}+P_iS_{i-1}\\ \end{aligned} \]

显然瓶颈在于那个卷起来的 \(P\circ S\)。不难发现可以拆成:

\[\sum\limits_{j=1}^{i-1} P_i^jS_{i-j}=\sum\limits_{j=1}^{i-1} \frac{P_i^i}{P_i^{i-j}}S_{i-j} \]

由于 \(P_i\) 只有 \(100\) 种,对所有的 \(P\) 开一个前缀和数组垒 \(\frac{S_i}{P^i}\) 即可。

*1783E Game of the Year, 2300

不敢笑。一开始写了整除分块。

显然问题等价于求所有的 \(k\) 使得 \(\forall i,\left\lceil\frac{a_i}{k}\right\rceil\le\left\lceil\frac{b_i}{k}\right\rceil\)。显然我们只需考虑所有 \(a_i>b_i\) 的部分。不难想到枚举 \(k\),和每一段 \([tk+1,(t+1)k]\),check 是否所有 \([b_i,a_i]\) 都一定在每一段以内。

对所有线段按照 \(l\) 排序,二分出每一段对应的 \(l\) 在线段中占有的区间,问题显然是求 \(r\) 的 RMQ。使用 ST 表即可做到 \(\mathcal O(n\ln n\log n)\)

1704E Count Seconds, 2200

气笑了。被骗了。

考虑如果每个点上都有充分多的值,那么每个位置上每个时刻都会减少 \(1\),那么答案就是汇集到唯一零度点上的值的和,拓扑排序即可。

然后样例二告诉我们这是不对的。因为有可能会在中途减到 \(0\),然后这个点就需要等待后面的值传播过来,那么它彻底变成 \(0\) 的时刻晚于汇集到它身上的所有值。

怎么解决呢?非常搞笑。我们可以证明,在 \(n\) 秒之后不会有任何点再重新陷入等待,此时我们可以直接跑最开始那个拓扑排序。

Proof.
假设这个点在 \(>n\) 秒之后陷入等待,说明有一个值将在 \(>n\) 秒之后才传播到它这里,这显然是不可行的,DAG 上最远的距离也不会超过 \(n\)

*2114F Small Operations, 2000

显然中转点是 \(g=\gcd(x,y)\),问题相当于对 \(\frac{x}{g}\)\(\frac{y}{g}\) 分解成最少的因数,使得每个因数都 \(\le k\)。直接在因数集上 dp 即可。

1654E Arithmetic Operations, 2300

为啥想到了根号分治也不会。

首先我们发现能放在一个等差数列里被保留的两个数 \(i,j\) 必然满足 \(a_i+d(j-i)=a_j\)。这启发我们考虑按照公差 \(d\) 根号分治。

对于 \(d\le B\),我们发现上述条件等价于 \(a_i-di=a_j-dj\),那么数众数即可。

对于 \(d\ge B\),我们发现它导致 \(j-i\le \frac{V}{B}\),那么我们可以枚举保留下来的第一项,之后可能的保留项不会在它之后 \(\frac{V}{B}\) 的更远处。于是也暴力数 \(\frac{a_j-a_i}{j-i}\) 的众数即可。

因为有公差的正负,所以正着倒着各做一遍。

*1781E Rectangle Shrinking

纯垃圾题目。先收缩高两行的矩形到不交状态,然后看怎么把高一行的矩形(线段)放进去。不难发现如果这个矩形的某一行被一个线段完全覆盖,那么可以删除这一行,否则我们显然应该收缩线段。剩下就是 dirtywork。

*1935E Distance Learning Courses in MAC

考虑拆位,从高位到低位枚举,钦定一个数来占据这一位。

先不考虑 \(x_i,y_i\) 相同的高位部分,这部分我们直接用 ST 表查按位 OR 即可。那么我们实际上只给每个数决策后 \(h_i=\operatorname{highbit}(x_i\oplus y_i)\) 位的情况。不难发现每个数实际上要么令第 \(h_i\)\(1\),后面转化为在 \([0,y_i-2^{h_i}]\) 中取,要么取 \(2^{h_i}-1\),把后面直接填满。

现在考虑怎么决策每一位上做 \(1\) 的数。不难发现我们应该贪心地选择选完之后距离 \(y_i\) 最远的那一个。

选完之后需要把这个数从中间位的数据结构中删去,表示它下一次可以做 \(1\) 需要到哪一位才行。值得注意的是,我们有可能会选到高位没有选走的数,此时就意味着这个数被填满,那么我们之后可以愉快地推平了。

交了一个能跑到 test 9 的暴力,我懒得写 RMQ 了。

*1864E Guess Game, 2100

有点难,但不多。

考虑传递的信息是什么东西。容易想到从高位往低位看,于是不难发现“不知道”其实指的是自己拥有当前比的最高位。所以整个博弈其实是下面的过程:

  • \(a\) 告诉 \(b\) 自己占有 \(a|b\)\(1\)-st 高位,现在要看 \(b\) 有没有。因为如果 \(a\) 没有的话他会 1 turn 立刻知道 \(a<b\)
  • 如果 \(b\) 没有,那么 2 turns 得出 \(b<a\)。如果 \(b\) 有,则 \(b\) 顺便往下看一位,如果 \(2\)-nd 高位 \(b\) 没有,那么他也将 2 turns 得出 \(b<a\)
  • 如果 \(a\) 没有 \(2\)-nd 高位,那么 3 turns 得出 \(a<b\)。如果 \(a\) 有,则 \(a\)顺便往下看一位,如果 \(3\)-rd 高位 \(a\) 没有,那么他将 3 turns 得出 \(a<b\)
  • 以此类推。

于是我们设 \(\operatorname{highbit}(a\oplus b)\) 前面 \(1\) 的数量为 \(c\),特别地如果 \(a=b\) 那么我们认为 \(c\) 就是 \(a,b\) 当中 \(1\) 的数量。那么:

\[ans= \begin{cases} c+1,&a=b\\ c+1,&c\equiv 1\pmod 2\land a>b\\ c+2,&c\equiv 1\pmod 2\land a< b\\ c+2,&c\equiv 0\pmod 2\land a>b\\ c+1,&c\equiv 0\pmod 2\land a< b\\ \end{cases} \]

现在考虑怎么对着整个序列算。不难发现任意一对不同的数产生的贡献都是 \(2c+3\),相同的数产生的贡献都是 \(c+1\),两部分贡献拆开,扫描线序列然后用 01-Trie 算 \(\sum c\) 即可。

*1763C Another Array Problem, 2000

没有小样例无法做的诈骗题。

不难发现对于 \(n\ge 4\) 我们可以用下面的方法把整个序列推成 \(\max\):找到一个 \(\max\),它总是有一边有大于等于 \(2\) 个元素,把那一边推两遍即可变成全 \(0\),再和 \(\max\) 推一遍变成全 \(\max\),再反过来消灭最初的 \(\max\) 来把另一边推成全 \(\max\)(要利用最初的 \(\max\) 是因为有可能这一边只有 \(1\) 个元素)。

\(n\le 3\) 直接分类讨论即可。

*2028D Alice's Adventures in Cards

dp,\(f_{i,0/1/2}\) 表示在哪个人手上获得了第 \(i\) 张牌。考虑到获得的牌单调递增,枚举现在获得的牌和来自的人,那么查询这个人这张牌前面的那些 \(p\) 当中有没有 \(1\) 即可。树状数组维护。

*1763E Node Pairs, 2200

显然相互到达的点具有传递性,所以连成完全图。于是相当于划分成一个序列 \(\{a\}\) 使得 \(\sum \frac{a_i(a_i-1)}{2}=p\)

同时不难注意到第二问是诈骗,在确定总点数的情况下显然连成链最优,那么所有点对里面除了 \(p\) 对互相到达的都是不可互相到达的,所以在得到第一问的答案 \(n\) 之后直接输出 \(\frac{n(n-1)}{2}-p\) 即可。

*1646D Weight the Tree, 2000

不难注意到不允许任意两个相邻的点同时满足条件,于是答案上界是最大独立集。显然获得一个独立集之后最小点权和的办法就是独立集中的点点权设置为 \(deg\),其他点设置为 \(1\),这对每个点来说都是点权下界所以点权和最小。

于是 dp 最小点权最大独立集即可。

*1765H Hospital Queue, 2200

如果 \(a_i\) 必须在 \(b_i\) 前面,考虑连有向边 \(b_i\to a_i\)

考虑一个人 \(u\) 能够放在位置 \(i\le p_u\) 的充要条件。不难感受到是:

  • 所有 \(p_j\le i\) 的人 \(j\) 们,算上 \(u\),可达的点的并集大小 \(<i\)。这样我们才能把这个人放在 \(i\)
  • 对于任意一个 \(i\le k\),所有 \(p_j\le k\) 的人 \(j\) 们,算上 \(u\),可达的点的并集大小 \(\le k\)

于是考虑怎么对每个 \(i\) 计算 \(p_j\le i\) 的人 \(j\) 们可达点的并集。不难发现按照 \(p\) 从小到大扫描,在有向图上扩展即可做到单次均摊 \(\mathcal O(n+m)\)。总时间复杂度 \(\mathcal O(n(n+m))\)

双倍经验 P1954,只多一个贪心拓扑序。

1657E Star MST, 2200

只会 \(\mathcal O(n^6)\)。招笑!

考虑 \(f_{i,j,k}\) 表示填写到权值 \(\le i\) 的边,现在已经挂在 \(1\) 上的点之间产生的不与 \(1\) 相连的边中还有 \(j\) 对没有给出边权,当前有 \(k\) 个点挂在 \(1\) 上。对于每种权值先挂点,再考虑一般的边。挂点时有多重集排列数的系数(因为没有安排这些点的编号,给编号是一个多重集排列数),赋权一般边需要乘组合数。

考虑这个做法的状态太臃肿了。实际上我们根本没有必要把挂点时新增的一般边先放到里面存下来到后面再决策。考虑这些边每一条出现的时候(显然按照我们的算法,每条一般边必然出现在两个端点中到 \(1\) 边权较大的那个点出现的时候)我们就已经知道它有 \(k+1-i\) 种方案了,所以立即可以算出这些边产生的贡献是 \((K+1-i)^c\),其中 \(c\) 表示新出现的边数。

于是复杂度可以轻易做到 \(\mathcal O(n^3)\)

【HT-097-Rainbow】核桃彩虹周赛

D. 旅游(travel)

题意 $n$ 个城市排列在一行上,$i$ 和 $i+1$ 城市由双向道路 $i$ 连接。确定一个排列 $p_n$,使得每次小 S 从 $i$ 走向 $p_i$,走完 $n$ 次之后每条道路的经过次数恰好为给定的 $\{a_{n-1}\}$。或报告无解。

\(1\le n\le 2\times 10^5\)

这题考试的时候想了很久,有几个我觉得挺难的观察。

考虑刻画这个 \(a_i\) 是什么。不难发现其实是 \(j\in [1,i]\)\(p_j>i\) 的位置个数和 \(j\in (i,n]\)\(p_j\le i\) 的位置个数之和。接下来我花了大量时间才发现这两个东西其实是相等的 /xk。考虑每当有一个 \(p_j>i\) 出现在 \([1,i]\) 中,同时就一定会有一个 \(p_k\le i\) 出现在后面,证明考虑反证或者分成两部分进行交换的构造性证明即可。

这说明每个 \(a_i\) 都是偶数。接下来我们不妨使 \(a_i\gets \frac{a_i}{2}\),然后容易发现:

  • \(|a_i-a_{i-1}|\le 1\)
  • \(a_i\le\min(i,n-i)\)

实际上判断完这两个条件就充要了。

考虑如何构造。考虑 \(a_i\)\(a_{i+1}\) 三种大小关系的意味。

  • \(a_i>a_{i-1}\):意味着 \([1,i]\)\(p_j>i\) 的位置个数比 \([1,i-1]\)\(p_j>i-1\) 的位置个数多了恰好一个。这说明,\(p_i>i\),并且 \(i\)\((i,n]\) 中。
  • \(a_i<a_{i-1}\):类似地,这说明 \(p_i<i\),并且 \(i\)\([1,i)\) 中。
  • \(a_i=a_{i-1}\):以上以外的所有可能。

我们容易猜测,\(a_i=a_{i-1}\) 的地方我们直接填入 \(p_i=i\) 很可能是对的。事实上确实如此。之后考虑如何构造,不难发现我们实际上就是想把 \(a_i<a_{i-1}\)\(i\) 填到前面去,\(a_i>a_{i-1}\)\(i\) 填到后面去,这启发我们两种类型的 \(i\) 按照从小到大的顺序互填——类似括号匹配。不难发现我们确定的那两个条件就是判定合法括号串的条件,并且序列里显然没有负数,所以这是对的。

P4055 [JSOI2009] 游戏

离谱。

由于移动是曼哈顿式的,不难发现从任何一个点出发走到一个点的时候下一步该谁操作与移动方式无关,可以直接确定下来。进一步地,这个操作者是谁仅与到起点的曼哈顿距离的奇偶性有关,所以我们可以直接对整个网格进行黑白染色,所有的同色点上的棋子都由同一人操作。

不妨考虑对网格连边抽象出图,会发现整张图构成了二分图,其中黑白点各是一部。然后我们发现实际上移动棋子的过程就是在两部之间切换的过程,一定可以获胜的情形即是无论对方怎么把棋子移回这边,我都能把棋子又挪回对面。

抽象出移动的路径,并分离两个人各自把棋子移动到对面去的那些边,可以发现构成了二分图的一个匹配。最终棋子停留在对面(先手获胜)的充要条件即是从先手这边挪过去的匹配永远比对面挪回来的匹配更大。随即可以发现这等价于起点被所有最大匹配包含。

Proof.
考虑如果后手移动回来的匹配是最大匹配,那么棋子绝不可能停留在对面。
如果当前点在所有的最大匹配中,则先手必然可以控制它的移动永远在一个最大匹配中(否则这个点周围的所有点都不在最大匹配中,这显然是矛盾的),而由于后手的匹配必然不包括这个点,所以总是可以比对面的匹配多一步,从而把棋子留在对面。

接下来考虑如何 flow 算出哪些点一定被所有最大匹配包含。

显然任意性比较麻烦,不妨补集转化为求不被某一个最大匹配包含的点。不妨先用 dinic 跑一个最大匹配出来,那么首先不在这个匹配里的点全倒闭了。根据经典结论,能从匹配中消除的点一定可以从一个非匹配点经过一条偶数长度交错路得到。这个显然是充分的,但必要性十分困难。

image

将所有非匹配点放入队列进行多源 BFS,只走交错路即可。

使用 Dinic 算法获得最大匹配即可做到 \(\mathcal O(nm(n+m))\)

posted @ 2025-12-21 00:01  Shunpower  阅读(33)  评论(0)    收藏  举报