ad-hoc 题目合集

APC001F

题目链接

一眼不可做,直接对边权处理是没有思路的。于是考虑边权转点权。

\(val_u\) 表示所有与 \(u\) 相连的边边权的异或和。

考虑现在对链的异或操作变为了什么,设当前对链 \(u\rightarrow v\) 异或上值 \(p\) ,对链上一个点 \(x\),我们分两种情况讨论。

  • \(x=u/v\),此时 \(val_x=val_x\oplus p\)
  • \(x\neq u/v\),此时 \(val_x=val_x\oplus p\oplus p=val_x\)

所以每次对链的操作转化为了对两个点操作,此时边权为 \(0\) 等价于所有点权为 \(0\)

不难想到每次最多只会让两个点的值变 \(0\) ,所以最优策略一定是优先找到两个相同的数,使其异或上自己。所以,每种数字最后只留下不超过一种

\(a_i\leq 15\),于是可以考虑子集 dp。设 \(f[S]\) 表示让集合 \(S\) 内的数都为 \(0\) 的最小步数,则转移为 \(f[S]=f[S']+f[S\oplus S']\),其中 \(S'\)\(S\) 的子集。时间复杂度 \(O(3^{16})\)

AGC018E

题目链接

三个矩形乱跑显然难搞,那就一点点推吧。

1. 从一个点到另一个点

不妨令一个点的坐标为 \((0,0)\),另一个点相对坐标为 \((x_1,y_1)\),方案数即为 \(\binom{x_1+y_1}{x_1}\)

2. 从一个点到一个矩形

首先考虑暴力咋搞,令 \(f((a,b)\rightarrow (p,q))\) 为从 \((a,b)\)\((p,q)\) 的方案数。

\[\sum_{x=x_1}^{x_2}\sum_{y=y_1}^{y_2} f((0,0)\rightarrow(x,y)) \]

而矩形是可以被拆分成四个 \(\text{2-side}\) 矩形的,具体的说,我们记 \(g(x,y)\) 为走到 \((x,y)\)\(\text{2-side}\) 矩形的方案数,则答案可表示为

\[g(x_2,y_2)-g(x_2,y_1-1)-g(x_1-1,y_2)+g(x_1-1,y_1-1) \]

然后考虑快速计算 \(g\)。砸个表上去。

然后你就发现 \(g(x,y)=f(x+1,y+1)-1\)

所以答案变为

\[f(x_2+1,y_2+1)-f(x_2+1,y_1)-f(x_1,y_2+1)+f(x_1,y_1) \]

加一减一消去了,所以是上边的形式。

这让一个矩形转变成了四个点

3. 从一个矩形到一个矩形

先大力写出暴力式子。

\[\sum_{x'=x_1'}^{x_2'}\sum_{y'=y_1'}^{y_2'} \sum_{x=x_1}^{x_2}\sum_{y=y_1}^{y_2} f((x',y')\rightarrow(x,y)) \]

然后用上文中的式子去掉两重循环

\[\sum_{x'=x_1'}^{x_2'}\sum_{y'=y_1'}^{y_2'} f((0,0)\rightarrow(x_2+1-x',y_2+1-y'))+... \]

在这里只写出一个结果。注意到从一个矩形到点和一个点到矩形的方案数是显然等价的,所以进一步写为

\[\sum_{x'=x_1'}^{x_2'}\sum_{y'=y_1'}^{y_2'} f((0,0)\rightarrow(x'-x_2-1,y'-y_2-1))+... \]

然后注意到上文在拆分求和以后依然是四个点到矩形的形式,依然可以套用上式化简。最后能把两个矩形都转化为四个点,做 \(4\times 4\) 次枚举后套用公式即可。

4. 从一个矩形经过一个矩形到一个矩形

由于上文中所述的矩形转点思想(姑且这么说吧 qwq),我们只需要考虑一个点经过一个矩形到另一个点的方案数即可。

整个过程可以拆分为两部分

  • 从起点到第二个矩形的边界
  • 从第二个矩形的边界到下一个点

由于要求最短路径,所以进入矩形的边界一定是下/左边界。枚举下边界和左边界上的点,然后再跑一次点到点即可。

5. 从一个矩形经过一个矩形到一个矩形的路径长度之和

终于到了本题要干的事情了。

考虑在 4 上做一些修改,把整个过程拆成三部分

  • 从起点到第二个矩形的边界
  • 从第二个矩形的下/左边界到第二个矩形的上/右边界
  • 从第二个矩形的边界到下一个点

观察从第二个矩形的边界跑到第二个矩形的边界这一过程,假设我们知道当前的两个点是 \((x_1,y_1)\)\((x_2,y_2)\),那么对答案的贡献便是 \(f((x_1,y_1)\rightarrow(x_2,y_2))\times (x_2-x_1+y_2-y_1)\) 这个可以拆成两部分计算。枚举左右上下边界上的点,跑一遍上文中的计算方式,但是要注意符号问题,同样的问题出现在 2,3,4 中。时间复杂度 \(O(n)\)\(n\) 为值域。

CF1707E

题目链接

第一道 3500。

下文中,我们称调用 \(k\) 次题面中所述的 \(f\) 函数后所得的区间为 \(f^k(l,r)\),下文中所述的对二元组 \((l_1,r_1),(l_2,r_2)\) 进行的加法操作后得到的结果为 \((\min(l_1,l_2),\max(r_1,r_2))\),二元组中的两个元素分别为 \(l,r\)\(p(l)\) 表示 \(p\) 这个二元组中的元素 \(l\)

首先看到这种一眼不可做的题先猜性质 qwq。

注意到每次操作区间带有可拆分的性质。即

\[f^k(l,r)=f^k(l,l+1)+f^k(l+1,l+2)+\ ...\ +f^k(r-1,r) \]

如何证明?考虑归纳。

首先 \(k=0\) 时显然成立。

\(k=1\) 时,我们设最小值\(mn\) 出现在位置 \(x\),最大值 \(mx\) 出现在位置 \(y\),则 \(f(x-1,x)(l)=f(x,x+1)(l)=mn\)\(f(y-1,y)(r)=f(y,y+1)(r)=mx\)。显然每两个二元组中一定有一个存在于右式中,故左右答案相等。

同理可推广到高次情况。

现在咋做呢?

我们设 \(g^k(x)\) 表示 \(f^k(x,x+1)\),那么答案一定是找到最小的 \(k\) 使得 \(g^k(x)=(1,n)\),而 \(f^k(1,n)=(1,n)\)(如果此时 \(a\) 中存在 \(1\)\(n\),否则除非询问二元组是 \((1,n)\),经过任意次变换都不可能是 \((1,n)\)),所以可以倍增做,预处理出所有 \(k=2^i\)\(g^k(x)\) 的值,询问时转化为对于是否二元组 \((l,r)\) 调用 \(2^k\) 次使得二元组不是 \((1,n)\),即 \(g^{2^k}(l)+g^{2^k}(l+1)+\ ...\ +g^{2^k}(r-1)\neq (1,n)\),答案即为次数加 \(1\)而上边的加法操作是可以 st 表维护的

问题转化为如何快速求 \(g\)\(g^{2^k}(x)=g^{2^{(k-1)}}(g^{2^{(k-1)}}(x))\),而 \(g^{2^{(k-1)}}(x)\) 是已知的,令其为 \((l,r)\),问题又变为询问 \(g^{2^k}(x)=g^{2^{(k-1)}}((l,r))\)仿照上文的询问 st 表维护即可

时间复杂度 \(O(n\log^2n)\)

P6982

题目链接

首先发现 \(\frac{n}{2}\) 是最奇怪的,考虑从这里入手。

假设我们知道了一个返回值为 \(\frac{n}{2}\) 的串,那么我们可以在 \(n\) 次操作后得到原串。具体做法如下。

首先取反第一位,然后对剩下的第 \(2,3,...,n\) 位按位取反。分情况讨论

  • 返回值为 \(\frac{n}{2}\),说明该位正确性与第一位不同。
  • 返回值为 \(0\),说明该位正确性与第一位相同。

在你得到了所有位与第一位的正确性关系后,将所有正确性不同的取反,做一次询问,返回值为 \(n\) 即为原串,否则为反串。

接下来考虑如何得到一个返回值为 \(\frac{n}{2}\) 的串。

大力随机!

考虑正确性,也就是说,我们要从 \(n\) 个位置中取出恰好 \(\frac{n}{2}\) 个位置使得该位与原串相同,剩下的不同,那一次成功的概率即为 \(\frac{\binom{\frac{n}{2}}{n}}{2^n}\)。那么在 \(500\) 次内问不出来的概率为 \((1-\frac{\binom{\frac{n}{2}}{n}}{2^n})^{500}\)。这个东西不会很大,因为 \(\binom{\frac{n}{2}}{n}\leq2^{n-1}\)。所以直接随机询问即可。

P5101

题目链接

首先题面对折叠给了个非常反人类的定义,这里来简化一下

  • 选择一个左端点是原串左端点的长度为偶数的回文串,保留其右半部分。
  • 选择一个右端点是原串右端点的长度为偶数的回文串,保留其左半部分并将其放到开头,然后将原串其余部分翻转后接在其后边。

并且由于厚度,染色操作必然在翻折前进行。

有一个显然的性质是,一个串最后能被缩到长度为 \(2\) 的串,其中的颜色必然不超过 \(2\) 个(因为翻折操作不会减少颜色种类数)。

考虑进一步推广,一个串能被缩短到长度为 \(2\) 的串,需要其除首位外每个连续段长度均为偶数,充分性是显然的,必要性证明如下。

若存在一个连续段长度为奇数且不在首位,则将其两端缩起来后,必定为 \(x...x,y...y,x...x\) 其中 \(y\) 有奇数个,此时两端的 \(x\) 无法翻折到一起,长度至少为 \(3\)

又注意到每个长度为偶数的连续段可以拆成若干个长度为 \(2\) 的连续段,为奇数的同理可拆出若干个长度为 \(2\) 的连续段+一个单独颜色,考虑对原序列进行划分处理。去除首尾的限制则可以通过枚举起始点解决。

接下来对每个小段进行考虑,我们钦定 \(c\) 为当前考虑的颜色

  • 如果小段内都为 \(c\),不更改。
  • 如果小段内其中一个颜色为 \(c\),将另一根线也改为 \(c\) 不劣。
  • 如果小段的颜色都不为 \(c\),则需要根据另一种颜色来决定更改。

设对于颜色 \(c\) 答案为 \(ans_c\),则有 \(ans_c=\min_{c'}(n-cnt_c-cnt_{c'}-cost_{c,c'})\),其中 \(cnt_i\) 为颜色 \(i\) 出现次数,\(cost_{c_1,c_2}\) 表示使用 \(c_1,c_2\) 的最小花费,\(c'\) 为另一种颜色,其实 \(cost_{c_1,c_2}\) 就是包括 \(c_1,c_2\) 两种颜色的小段数量。

暴力枚举做到 \(O(nm^2)\)

枚举每个包括 \(i\) 的小段,开桶维护 \(cnt_{c'}\) 根据上文所述进行更改即可做到均摊 \(O(n)\)

ABC235Ex

题目链接

由于我们无法定义点集,我们不妨建立一个集合和整数的函数关系 \(g\)\(g(S)=x\) 表示 \(x\)\(S\) 被构建的最小次数。这里的 \(S\) 与上文意义相同。不妨考虑定义一个多项式 \(f(G)\)\([x^i]f(G)\) 表示在图 \(G\) 中,\(g(S)=i\)\(S\) 数量,其中 \([x^i]F\) 表示在多项式 \(F\) 中,\(i\) 次项的系数。不难发现每个 \(S\) 唯一对应一个 \(x\),因此答案即为 \(\sum\limits_{i=0}^k[x^i]f(G)\),其中 \(G\) 为给定的图。在这里,对于两个不连通的子图 \(G_1\)\(G_2\),两个多项式 \(f(G_1),f(G_2)\) 相乘的意义是 \(f(G)\)\(G\) 是将 \(G_1\)\(G_2\) 合并后的图。

不妨简化条件,首先设原图是一个树,且边权互不相同。

我们将边权排序并从小到大考虑每条边,对于当前边 \(e\),设其连接的两个连通块分别为 \(T_1,T_2\),连接后的连通块为 \(T\),我们进行分类讨论:

  • 我们让所有对 \(T\) 进行的操作选择的 \(x\) 都小于 \(e\) 的边权:这意味着两个连通块进行的操作是独立的,故答案为 \(f(T_1)*f(T_2)\)

  • 存在一个操作选择了一个不小于 \(e\) 的边权 \(x\):这意味着两个连通块必定被染红。

因此,我们将其这两个多项式合并的答案为 \(f(T_1)*f(T_2)-x^2+x\)。也就是说,使得两个点集完全变成红色由之前的至少两次变为了至少一次。

到这一步我们其实也看出了为什么要让边权互不相同,如果存在相同边权,那么选择不小于 \(e\) 的边权后合并的连通块个数将不确定。

不妨设对于一个连通块 \(T\),考虑到所有边权为 \(x\) 的边时其多连通的所有连通块为 \(T_1,T_2,...,T_m\),则答案为 \(\prod\limits_{i=1}^mf(T_i)-x^m+x\)

最后使原图不是树,我们将证明,\(f(\text{MST}(G))\) 的答案和 \(f(G)\) 的答案相同。\(\text{MST}(G)\) 表示 \(G\) 的最小生成树。

设一条不在最小生成树上的边 \(e\),由于最小生成树的基环性质,则在其两端点的路径上任取一点 \(u\) 并进行一次 \(u,w(e)\) 的操作与有无 \(e\) 都是等价的。故答案不变。

由于一共合并 \(O(n)\) 次,单次合并复杂度为多项式乘法的 \(O(k^2)\),故总复杂度看起来是 \(O(nk^2)\) 的。

官方说复杂度可以证明是 \(O(nk)\) 的,但是我不会证,这里给出我的 \(O(nk\log n)\) 理解。

考虑构造一个复杂度的上界,对于合并为大小为 \(S\) 的连通块,其最坏复杂度是 \(O(\dfrac{S^2}{4})\) 的。

所以最坏的合并方案是一直合并两个大小相同的点集。将会发生 \(\dfrac{n}{2}\) 次大小为 \(1\) 的合并,\(\dfrac{n}{4}\) 次大小为 \(2\) 的合并,\(\dfrac{n}{2^{i+1}}\) 次大小为 \(2^i\) 的合并。单次的复杂度为 \(O(n2^i)\),而 \(2^i\leq k\),故总复杂度上界为 \(O(nk\log n)\)

P4672

题目链接

细节很多的一道思维题。

上来一个直观的感受是,如果我们能找到两个根,我们就能通过 bfs 算距离把树划分为两半,然后检查两边的树是否同构。更进一步的,我们发现如果能找到一对对应点,我们也能够把树划分成两半。

现在的问题是怎么找到这对对应点。考虑环的形成过程,我们发现,对于一个合法的图,当我们删去一个环的时候,整个图会断成若干个连通块,且每个连通块中最多包含两个环上的点,这两个点一定是对应点。原因是一个环环上的边一定是原树上的若干条对称树边,而父亲到儿子的路径唯一,若合法一定不会出现断开环后一对有父子关系且在环上的点出现在同一连通块中。

现在的问题有两个,一个是特殊的情况,另一个是如何判定树同构。

首先考虑后者,对两边 bfs 重标号,检查父子关系即可。

然后考虑前者,分情况考虑。

  • 没有环。

    此时整个图是一条单链,我们判断点数奇偶性即可。

  • 不存在有两个环上的点的连通块。

    考虑此时图的形态,一定是一个大环上套了一堆链。我们继续讨论。

    • 不存在两个度数为 \(1\) 的点。

      意味着图是一个大环,直接判断点数奇偶性即可。

    • 存在两个度数为 \(1\) 的点。

      把这两个点当根跑上面的判定即可。

当然还有一些情况,比如两边不是树,两边点数不同等等,也要一一判掉,前者可以判点数、叶子数和边数的关系,后者 bfs 的时候检查一下即可。

LOJ6669

题目链接

我们首先可以做 \(n\) 次询问知道深度,现在我们可以通过询问两个点之间的距离得到 lca 的深度。

那么我们考虑一层一层加点,对于每一次加点,上面的树的结构已知。问题转化为快速求其上面的点是哪个。考虑维护一个树剖结构,每次询问根节点所在的链底,通过这些点的深度和距离得出 lca 的深度。由于这是一条重链,且为二叉树,所以我们直接去 lca 的轻儿子递归,边界条件为深度相差为 \(1\)

考虑询问次数。由于重链剖分的性质我们知道重链总数是 \(O(\log n)\) 条的,所以这样做的总询问次数是 \(n+n\log n\),但是卡不满。

P7515

题目链接

\(c_{i,j}=a_{i,j}+a_{i,j-1}\),那么有 \(b_{i,j}=c_{i,j}+c_{i-1,j}\)。据此可以推出来 \(c\),然后可以推出来 \(b\) 的一组合法解。现在我们考虑如何调整出一组满足条件限制的解。

注意到 \(c_{i,j}=const-(-1)^i c_{1,j}\) 依然是一组合法解,我们不妨通过这种方式来调整答案。注意到对答案的限制其实构成了若干个不等式,那么我们对于每一个 \(c\) 都可以建出一个点,然后爆算出剩下的数对于其取值的限制,跑差分约束判断是否有解即可。

构造方案可以直接通过差分约束解决。

CF827F

题目链接

注意到一个性质是,如果我们在 \(t\) 时刻经过一条边 \((u,v,l,r)\) 到达了点 \(v\),那么我们一定能在 \(t+2k,k\in \mathbb{N}^*\land t+2k<r\) 时刻到达点 \(v\)。这启发我们分开奇偶性考虑。

但是直接维护点是不好维护的,因为以最小时间走到一个点会出现走不出去的情况。但是边是可以维护的,以最短时间到达一条边意味着以后任何一个奇偶性相同时刻都能到达该边。因此我们试图把一个点 \(u\) 拆成奇偶两个点 \(u_0,u_1\),把一条边首先拆成两条单向边。对于一条单向边 \(u\rightarrow v\),我们连 \(u_0\rightarrow v_1\)\(u_1\rightarrow v_0\),分别代表在奇偶时刻走过的情况。

接下来考察一个类 dijkstra 状物。对于一个时刻 \(t\),我们将所有将所有在时刻 \(t\) 存在且未在之前进行松弛的边加入图中并进行一轮松弛。注意到每条边最多被松弛一次,故时间复杂度仍是 \(O(n\log n)\)

LOJ3985

题目链接

大概是这三年以来见到过的最厉害的题,思路自然而不套路。

下文中令 \(n=N,s=S\)

首先我们考虑一个限制为 \(M=1002\) 的做法,对于一个长度为 \(n\) 的字符串,我们考虑设计一个算法去按位定位每一位的答案。假设当前我们要确定第 \(i\) 位的值,那么考虑构造一种序列,使得前 \(i-1\) 位不会影响答案且最后答案只与第 \(i\) 位的值有关。也就是说,在到达 \(i\) 后,答案始终固定。而对于一个位置 \(i\),简单构造可知若 \(i=a_i=b_i\),则到达此位置后的结果不影响答案。因此不难想到构造序列 \(a=[1,2,\cdots,i-1,i,i,i+1],b=[1,2,\cdots,i-1,i+1,i,i+1]\)。期望得分 \(10\) 分。

现在我们进军 \(M=502\)。考虑上面的做法实质上能够让我们在 \(M=L+3\) 的长度限制之内确定一段前缀的答案,那么我们现在自然想到能不能也在 \(O(L)\) 的限制内确定一段后缀,那么我们知道所有 \(j\in[i+1,n]\) 后缀的 \(s_j\) 的值,要推出来 \(s_i\) 的值,这相当于判定一段后缀是否和某个给定串 \(t\) 相等。具体而言,我们试图构造两个数列,若当前机器中的字符为 \(i\),则意味着当前的后 \(i\) 位和 \(t\) 的前 \(i\) 位相同,这个可以暴力构造,但对于不同的字符串有不同的形式,故具体实现和构造方式可以参考代码。

这个做法似乎没啥前途,我们不妨跳出这个来想一想。题目的要求实际上是要我们求 \(n\)\(0/1\) 变量的值,而求未知变量的值我们能够想到的一个做法是构造若干线性无关的方程。而我们还知道存在一组合法解使得 \(x_i\in\{0,1\}\),因此我们可以考虑模 \(2\) 意义下的方程组。考虑每次询问出下标 \(i\) 满足 \(i\equiv q\pmod p\)\(s_i=1\)\(i\) 的个数模 \(2\) 后的值。通过手玩发现可以构造两个长度为 \(p\) 的环,能改变所在的环的位置只有在环上的第 \(q\) 个位置且此时走到的 \(s_i\)\(1\),实际的构造可以参考代码,本质上是 kmp 自动机。

打表发现通过这个方法获得 \(1000\) 个独立方程组的 \(p\) 的最小值是 \(57\),故此时有 \(M=114\),求出方程组后高斯消元或其它做法即可。

其实到了这一步以后正解自然的已经出来了。结合前两种做法我们可以把序列长度缩短到 \(799\),也就是说我们此时只需要求出 \(799\) 个独立的方程组,此时 \(p\) 的最小值为 \(51\),恰好顶着上界。

于是做完了。

提交记录

CF1394C

题目链接

完全不是字符串的字符串题/cf。

注意到相似的定义本质上是字符串中 \(\texttt{B}\)\(\texttt{N}\) 的数量相同。而操作也是围绕着 \(\texttt{B}\)\(\texttt{N}\) 的数量进行的,所以每个字符串实质上等价于一个二元组 \((b,n)\),分别表示字符串中 \(\texttt{B}\) 的数量和 \(\texttt{N}\) 的数量。考虑此时操作的本质是什么,相当于是让 \((b,n)\) 转移到 \((b±1,n),(b,n±1),(b±1,n±1)\)

那么此时进一步考虑计算答案。看到最小化最大值想到套路二分。考虑每个二元组对答案的限制是什么。假设当前二分到一个答案 \(x\),前两种转移是容易处理的,也就是说对于一个合法答案 \((b_0,n_0)\),其有 \(b_0\in[\max\limits_{i=1}^n (b_i-l),\min\limits_{i=1}^n (b_i+l)],n\in[\max\limits_{i=1}^n (n_i-l),\min\limits_{i=1}^n (n_i+l)]\),但加上第三种限制可能有点难以直观理解,我们不妨将其看为一个三元组 \((b,n,b-n)\),那么此时对第三维的限制就变成了 \(b_0-n_0\in[\max\limits_{i=1}^n (b_i-n_i-l),\min\limits_{i=1}^n (b_i-n_i+l)]\)。也就是说我们得到了三个关于 \(b\)\(n\) 的区间。判断这三个区间是否有交即可。

最后的问题是构造方案。根据上面的我们得出了一个区间,那么任取在区间中的两点即可,可能要同时注意一下第三维对答案的限制。

CF321D

题目链接

考虑设一个 \(c(i,j)\) 表示第 \(i\) 行第 \(j\) 列是否被反转。观察此时 \(c\) 的性质。不妨以列为例。注意到如果第 \(i\) 行的子矩阵被反转,则 \((i,m)\) 一定会被反转,而任意一个在第 \(i\) 行覆盖的子矩形一定覆盖了 \(c(i,j)\)\(c(i,j+m)\) 二者中的恰好一个。所以不难得到一个约束条件是 \(c(i,m)\oplus c(i,j)\oplus c(i,j+m)=0\)。转到行上的话同理,那么有 \(c(i,j)\oplus c(m,j)\oplus c(i+m,j)=0\)。那么根据这两个限制如果求出来左上角大小为 \(m\times m\) 的矩形就可以还原出 \(c\),进而还原出操作序列。

此时 \(c\) 有很好的性质,如果考虑左上角大小为 \((m-1)\times (m-1)\) 的矩形,其 \(c\) 的填法相互独立,即可以同时达到最优解。现在需要解决的只有第 \(m\) 行和第 \(m\) 列的填法。那么我们枚举行的状态,注意到此时我们可以直接推出第 \(m\) 列的状态,此时前 \(m-1\) 行的信息对第 \(m\) 列构成了一些限制,那么此时对于每列直接取得最大值,然后对于每列的最大值取加和即可。

CF1427F

题目链接

首先不考虑轮流的问题。我们将第一个人摸到的牌记为白色,剩下的记为黑色。我们考虑求出一组合法的顺序使得牌堆能被取空。我们试图维护一个栈结构,维护若干个大小不超过三的元组。顺序扫描序列,每次取出栈顶,如果当前卡牌颜色和栈顶维护的元组相同,我们将其加入栈顶的元组,否则我们新开一段。然后若栈顶元组大小为三就将其加入答案序列的末尾并将栈顶出栈。由于保证有解,所以栈一定被删空,那么答案序列按顺序输出即为一组合法方案。

接下来考虑怎么轮流。注意到元组之间是有一些限制关系的,形如第 \(i\) 个元组必须要在第 \(j\) 个元组之前取得。我们试图通过一种方式刻画出来限制关系。考虑上面所述的栈过程,我们维护一个森林,对于其中的一棵树,树上的每个节点代表了一个元组,当一个元组入栈的时候我们将其和栈顶所代表的元组连边。那么限制关系相当于一个元组被取当且仅当其子树里的所有元组都被取走。

那么我们可以考虑一种剥叶子的构造方式。每次选出一个颜色要求和当前相同且为叶子的元组,将其添加到答案序列中,然后将其删掉。

但现在存在一个问题,即我们如何保证每一步都存在一个这样的叶子供我们删除。我们首先来观察森林中的树的一些性质。注意到栈每相邻两层之间是异色的,所以树的任意相邻两层之间也是异色的。然后我们回到原命题,分此时是要取白色还是黑色的讨论。

对于白色的情况,我们有白色和黑色的节点数量相同。若此时不能取到任何一个叶子,则这个森林必定为由一些黑白交错的链的组成,且所有链白色节点为根。但原题保证有解,所以至少有一个链底为黑色。故不会由这种情况,我们任取一个点即可。

对于黑色的情况,此时黑色节点的数量比白色的数量多 \(1\),考虑对此时黑色根的数量进行讨论。如果有多个根,则可以仿照白色的情况证明一定有黑色叶子。否则考虑单根的情况,由于我们要保证至少有一个根颜色为黑色,如果此时根有儿子,我们还是可以仿照白色证明一定有黑色的叶子,否则我们保留这个根,相当于保留了一个点到最后删,这其实和取白色本质相同,仿照白色的情况取一个其它的黑叶子即可。

posted @ 2023-07-14 23:30  -Comρℓex-  阅读(321)  评论(2编辑  收藏  举报