构造/交互/Ad-hoc专题
P6663 [POI 2019] Układ scalony
首先,构造上下界。上界显然是 \(nm-1\),下界需要分奇偶讨论。右下左上联通,所以需要至少 \(n-1+m-1\) 的长度,我们发现对于 \(m,n\) 中有一个奇数的情况是可以满足的。在奇数那里从中间一列劈开,然后分别向两边连。对于偶数,我们无法到最中间的那个,那么只能选择相对更靠中间的那个。但是如果我们这么选
会造成长度加一,也就是 \(n+m-1\)。
最后的构造很显然就是调整法了。我们逐步将最小情况往大去调整,直到遇到答案。以 \(n\) 为奇数为例,我们先构造出红笔的主链,然后目前潜在的连边方式是黑笔的下界,如果我们要调整就一点一点地调整成蓝笔的上界,按照那个螺旋线一点点走就行。
我们可以设置一个标号数组,\(f_{i,j}\) 表示该点连边的朝向,初始化就初始黑边朝向即可。然后如果要变更,就改成蓝笔朝向。
本题在 \(n,m\) 为偶数的时候的构造,初始状态不要设置为图 \(1\) 中那种最小值情况,而是同理设置为图 \(2\),方便后续调整构造,图 \(1\) 形态不方便调整。
P9837 汪了个汪
由于题目要求二元组不同,于是思考二元组特征。
发现一共要填 \(\dfrac{n(n+1)}{2}\) 个二元组,而二元组的个数恰好也是 \(\dfrac{n(n+1)}{2}\),于是就是要根据二元组特征给全体二元组分类。且最好每一类的个数分别是 \(1,2...n\) 这样子正好对应每一行。可以根据二元组两个数之差来分类,这样子正好满足上述条件。
但是我们无法这么去安排数字,下面是一个小技巧,如果可以(相同数字代表一类)
这么放,那么我们同样可以
于是我们可以按照 \(x~x+1~x-1~x+2~x-2...\) 这么来放。最后根据长度排序即可。
CF1325C Ehab and Path-etic MEXs
首先特殊情况---链。 随便填。
其他情况的几种思考方式
-
可以自己试几组或者打表,发现答案均为 \(2\) ,于是往 \(2\) 上面构造。
-
根据 \(mex\) 性质考虑分离几个最小值,因为一条链上的一个点对这条链最多有两条边的贡献,所以取前三小值 \(0 1 2\) 放在一个点的三条出边上。
我自己的想法是考虑到要求的是 \(mex\) 的最大值以及 \(mex\) 的性质,于是可以想到一条叶子到叶子的路径比其他路径更可能对答案产生贡献。(好像对本题没啥用)
P7915 [CSP-S 2021] 回文
这题的构造策略是先选取序列的第一个(最后一个同理)加入 \(b\) 中,发现与 \(a_1\) 相同的那个 \(a_x\) 必须最后放入序列中。于是可以在 \(a\) 数组中以 \(a_x\) 为分界点,此时切记不可再考虑选取 \(a_2\) 或者 \(a_{2n}\) 再次选取分界点。而是应该根据 \(a_x\) 为最后一个推导出 \(a_{x-1}\)或者 \(a_{x+1}\) 为潜在的倒数第二个,于是在序列两端寻找能否找到与 \(a_{x-1}\) 或者 \(a_{x+1}\) 相同的数作为 \(b_2\) 。以此类推,即可完成构造。
AT_arc144_c [ARC144C] K Derangement
构造可行解,在条件允许范围内微调使得更优。判断一下如果该数往前放的话,目前的位置可以有其他数字填补就可以进行操作。
CF1311E Construct the Binary Tree
很显然的就是先构造出一组极限情况,然后不断调整。这里以先构造一棵满二叉树为例。构造出以后,感觉自己思路还是有点乱,想的有点放开了,以为是一堆点移来移去,这样子显然是很完成构造题的。还是要大胆猜想出一个一般性策略然后实现。由于极限情况是一条链,所以我们可以把目标设置为链形。首先维护一条链,然后不断把树上节点挂上去。如果 \(rest_d\) 突然小于 \(0\),说明目前链长大于 \(-rest_d-dep_i\),故一定可以在链上找到一点使得 \(rest_d =0\) 并且该点没有挂上子节点,往上放就可以了。
CF1916F Group Division
考虑动态构造这个集合,每次选取剩余图上的与选取图联通的非割点加入即可。
如果要严谨点,可以证明一下存在性。
CF1736D Equal Binary Subsequences
首先 \(0~1\) 个数不相等肯定不行,我们可以大胆猜测一下个数相等的时候必然可以。其实我们也可以发现满足情况的可能很多,所以可能并不能直接找到一个通法。但这也说明了操作空间很大,我们可以钦定一种方案,强行构造。肯定选择相对便利的方案尝试构造,如果两组中对应位置在 \(s\) 中差距过大,那么难以操作,于是我们可以采取一些方法使得两组中对应位置相邻。效果就是类似 \(0011001111110000\) 。考虑分组,\((i,i+1)\),当 \(s_i=s_{i+1}\) 显然可以,我们将不相等的位置提取出来,必定形如 \((1,0)~(0,1)\) 交替着选出 \(0~1\) 然后平移即可。
CF1521E Nastia and a Beautiful Matrix
构造最小矩阵,一般要考虑答案下界,我们发现在 \((2x,2y)\) 的位置填入 \(0\) 剩下的位置填入 \(0\) 这样子显然是最大化的。此时可以填入 \(n^2-\lfloor \frac{n}{2}\rfloor^2\) 个数。设出现次数最多的数出现了 \(Max\) 次。那么为了实现要求 \(2\),需要满足 \(n\lfloor \frac{n}{2}\rfloor \ge Max\),于是二分出最小的边长同时满足两个条件即可。这只是必要条件,为了使得结论充要,下面我们需要给出一个满足条件的构造。条件一是已经满足的了,条件二需要我们让相同数字尽可能在同一行或者隔 \(2\) 行及以上,而非相邻行。直接对于 \(a_i\) 排序,把 \(a_i\) 个 \(i\) 依次放到一个序列中。按照序列顺序放到所有 \((2x+1,y)\) 上,放完之后再放 \((2x+1,2y+1)\) 这显然是更可能的去贴合条件二的情况。下证这构造满足条件二,发现对角线的两个数在序列中位置相差 \(\ge n\lfloor \frac{n}{2}\rfloor\),由上述二分可知,没有某个数出现次数大于 \(\ge n\lfloor \frac{n}{2}\rfloor\) 因此得证。
CF1365G Secure Password
首先可以转化一下题意:每次可以询问一个集合,要求最后对于每一个 \(i\) 需满足询问的集合中不含 \(i\) 的集合的并集等于全集去掉 \(i\)。
其实就是一个集合划分问题,再进一步转化一个上面的条件也就是对任意 \((i,j)\) 满足 \(j\) 出现在一个不含 \(i\) 的集合中。于是我们可以通过元素特征来划分集合。\(i\) 和 \(j\) 不同当且仅当二者的二进制表示中有一位不同,这启发我们考虑二进制的每一位分别询问下标的当前位为 \(0\) 和 \(1\) 的元素的集合。但是这样操作次数是 \(20\) 次。
如何减少操作次数呢,发现操作次数是等于集合总数的,于是我们可以通过减少集合总数来削减操作次数。在当前的划分方式下 \(20\) 个集合确实是必要的,因为只有这样才能区分出那些只有一位不同的数,所以我们可以选择更具有特征性的划分方式。
我们发如果固定 \(1\) 的个数这样不需要对于每一位正反查了,因为如果当前位 \(i\) 为 \(0\) 而 \(j\) 为 \(1\),那么必然存在另一位使得 \(i\) 为 \(1\) 而 \(j\) 为 \(0\),只需要在 \(1\) 的位置统计就可以了,这样就不需要正反询问了。
为什么询问次数上限是 \(13\) 呢,因为 \(C_{12}^i \le C_{12}^6 <1000\),而 \(13\) 恰好满足条件。
P9721 [EC Final 2022] Inversion
区间逆序对显然是不好得出什么结论的,于是我们考虑将区间逆序对转化为有用的东西。
这里一定要敢想,交互题一开始的思路就是先能做出来,再考虑次数限制。所以我们不要吝啬操作次数。我们发现可以用 \(4\) 次询问容斥原理得出 \(a_l\) 与 \(a_r\) 的相对大小关系。
得到的关系只是相对关系,这启发我们动态地维护相对大小,最后就可以得到总的序列。
设 \(pos_i\) 为目前相对排名为 \(i\) 的数的位置,\(a_i\) 表示 \(i\) 位置目前的相对排名。
每次新加入一个 \(p_i\),我们要求出 \(a_i\) 也就是 \(p_i\) 的相对排名。可以二分一下排名就行了,用所给函数来比大小。最后还需要来考虑一下次数。
第一个优化是记忆化。第二个优化发现对于 \(i\) 的每个询问要用到两次 \(f(k,i-1)\),我们很可能要调用函数计算,但其实不用,因为我们已经得出了前 \(i-1\) 个数的相对大小,所以可以直接判断。故其实一次询问只需要调用两次函数。
P3641 [APIO2016] 最大差分
\(T=1\), 的时候我们直接询问 \((0,10^{18})\) 便可以得出最大最小数,然后把最大最小数往中间缩一就可以得到次大和次小,以此类推得到整个数列。
\(T=2\),次数约束的是区间内数的个数,我们发现区间内数的个数越多,答案应该是越小的,而我们要求的是最大化答案,所以两者之中存在一个平衡。这里我们取 \(B\) 为答案下界,\(B=\frac{a_n-a_1}{n-1}\),每次跳跃着查询即可。答案只会是上一个块的最大值和当前块的最小值之差。考虑 \(M\) 是否符合要求,第一次 \(M \gets n+1\),后面会询问 \(n-1\) 次,总共覆盖到 \(n-2\) 个数,于是 \(M \gets n-1+n-2\),所以总数是 \(3n-2\)。
CF1158C Permutation recovery
一眼线段树建图+拓扑排序。不过还有更简便的方法。不过仔细考虑一下就是需要满足 \(i \to p_i\) 不相交就行了,于是单调栈判断一下就行了。考虑 \(-1\) 如何处理,我们发现 \(i\) 和 \(p_i\) 越近越容易满足条件于是直接设为 \(i+1\) 即可。然后需要构造,我们肯定是先构造出约束条件最少的,所以直接按照 \(p_i\) 降序,\(i\) 升序把 \(n-1\) 填入即可。
CF1354G Find a Gift
基本想法肯定是找出一些石子做参考物,然后比较。
问题是我们很难找到很多石子,但是发现石子的个数大于一半,且重量唯一最大,于是随机 \(\log n\) 个位置取重量最大的就大概率是石子了。现在我们得到了一个石子,显然是不够支持我们做大规模询问的,我们单组询问的规模是和已知石子的个数相等的,这里可以倍增,如果目前询问的一组里面没礼物,那么就必然全是石子且可以供我们所用。
CF1493F Enchanted Matrix
发现行列独立,可以分开处理。只需要在 \(n\) 或者 \(m\) 的约数中寻找。对于任意 \(r\),如何判断合法性呢,根据 border 结论,只需要比较 \((1,n-r)\) 与 \((r+1,n)\) 即可。但是本题要求不重叠,我们不能这么问。拆分一下即可,\((1,mid)~(mid+1,2*mid)\) \((1,mid)~(mid+r+1,2*mid+r)\)
CF1514E Baby Ehab's Hyper Apartment
先确定思路,我们判断大部分联通应该都是用到了联通传递性。于是根据竞赛图的性质我们先找出一条哈密顿路,然后顺着走显然就可以了。现在要逆着往回走,我们发现哈密顿路上越靠前的点可以走到更多的点,因为后继点能到达的地方他们也必然可以到达。这里就出现了单调性,可以通过多点查询双指针查一下。如何找到哈密顿路呢,这里可以采用合并法也就是合并 \((l,mid)\) 和 \((mid+1,r)\)。先找到两段的起点,看哪个起点可以指向另一个起点就将其作为总的起点,以此归并,可以直接 stable_sort 一下,比较函数就是点点查询。注意一下点集查询只能查是否有边,不能查所有边,所以可以考虑反过来通过没有边得出点集内所有都不可达。
CF650E Clockwork Bomb
初始树为 \(T1\),目标树为 \(T2\)。
考虑一下下界显然就是在 \(T1\) 在 \(T2\) 中没有出现的边的数量。
但是我们需要满足每次操作完仍然是一颗树。我们发现某个节点只要向上连边就必然保持树的形态,如果向下连边就会出现环。于是我们从叶子节点开始向上遍历即可。
注意处理特殊情况,\(T1\) 和 \(T2\) 中父子颠倒。如果在 \(T1\) 中 \(u\) 为 \(v\) 父亲,可是在 \(T2\) 中 \(v\) 为 \(u\) 父亲,那么我们要保留边 \((u,v)\),可以在从下往上遍历到 \(v\) 的时候,如果 \(v\) 要连自己在 \(T2\) 中的父亲的话,就要断开 \(T1\) 中的边 \((u,v)\) 否则可能成环。矛盾。
于是我们将断开 \(T1\) 中的 \((u,v)\),改为断开 \(T1\) 中 \((fa_u,u)\),这样既保留了边 \((u,v)\),又保证不会成环。可是同理如果 \(T1\) 中的 \((fa_u,u)\) 在 \(T2\) 中也出现过怎么办呢,我们可以采用并查集,找到该链上第一个不同时出现的边断掉即可。
P3514 [POI2011] LIZ-Lollipop
看到这题我的第一反应是每次 \(+-1\) 造成值域连续性,本题中如果是 \(0 1\) 序列的话值域也是连续的。可是这里有一个 \(+2\),按照前面的思路来想,可以发现这里是 \(2-\) 连续的。
假设 \([l,r]\) 和为 \(x\),如果两个端点是 \(1\),我们可以同时拖动两个端点使得其变成 \(x-2\),如果两个端点中出现一个 \(2\),我们也可以减去它构造出 \(x-2\)。
CF468C Hack it!
我们发现单独的各位数字累加没有什么规律或者好用的性质。
于是可以思考两两配对。就是令 \(p=\sum\limits_{i=1}^{10^{18}}i \bmod a\),然后把上界 \(+1\),下届 \(+1\),就可以发现增量就是 \(1+18 \times 0=1\),一直增加直到满足要求即可。
P7115 [NOIP2020] 移球游戏
先思考 \(n=2\) 时候的解法,记录两个栈为 \(s_1\) 和 \(s_2\),分别目标为 \(1\) 球和 \(2\) 球。我们现在想要其中一个栈变成全 \(1\)。我们发现 \(s_1\) 和 \(s_2\) 都往空栈里面放一点东西进去似乎只有暴搜放进去的顺序然后 \(2\) 和 \(3\) 栈互相搞一下的很暴力的做法,没有可扩展性。有没有什么好办法去分离 \(1\) 和 \(2\) 两种小球呢,只有两个空栈能办到。我们现在只有一个空栈,转念一想,其实我们可以再创造半个空栈,设 \(s1\) 中有 \(a\) 个 \(1\),那么我们只需要从 \(s_2\) 中挪 \(\min(a,m-a)\) 个球给 \(s_2\),然后将 \(s_1\) 中球依次弹出,分别放到 \(2\) 和 \(3\) 中这就实现了分离。
那么对于 \(n>2\) 的时候呢?把问题转化到 \(n=2\)!直接设置一个阀值 \(x\),然后 \(\operatorname{solve}(l,r)\),把 \((l,r)\) 分成两半,两边两两匹配,然后大的到一边小的到一边就行了。
还有一种解法是按照 \(n=2\) 的相同手法对于双栈进行排序,使得 \(\max s_1 \le \min s_2\),然后对于所有栈归并排序一下就行了。
P8150 再会 | Sayounara
可以发现由于交互库只能返回 \(\sum a_i-\min a_i\) 的结果,最小值被减去了。所以对于区间 \([l,r]\) 其最小值是一个隐藏信息,不管再怎么用区间内的数去组合询问,都无法得到最小值。
将上述思想扩展至全局,全局最小值更是不可能由操作一得到。所以我们的有一次询问操作二的机会肯定是留给全局最小值的。同时可以发现,一旦我们得到了全局最小值就一定可以在 \(n-1\) 次操作一之后还原整个数组。
所以现在的任务就是用 \(301\) 次操作一和 \(1\) 次操作二确定序列最小值的位置。
试了很久之后,想起来 P9721 [EC Final 2022] Inversion,那一题中是通过 \((l,r),(l,r+1),(l-1,r),(l-1,r+1)\) 四个区间的返回值异或在一起得到两个端点的大小关系,这启发我们不一定是要独立地分析每个询问的返回值,可以考虑将询问的返回值通过运算组合在一起。可以通过类似差分/减法运算使得某个信息暴露出来。
于是我们考虑试一下 \(query(l-1,r)-query(l,r+1)\),看看能否得到 \(a_{l-1}\) 和 \(a_{r+1}\) 的大小关系。
设 \((l-1,r)\) 和 \((l,r+1)\) 的最小值分别为 \(p,q\)。如果两者返回值相等,根据元素互不相等,可以得到 \(a_{l-1}=p\),\(a_{r+1}=q\)。如果前者返回值大,可以得出 \(p=q\),\(a_{l-1}>a_{r+1}\)。
我们可以惊奇地发现我们基本得到了 \(a_{l-1}\) 和 \(a_{r+1}\) 的大小关系,虽然在有的情况不能准确得出。同时可以得到一个更有用的情况,也就是最小值的分布位置。第一种情况可以得到最小值在两个端点,第二种情况可以得到最小值在 \([l,r]\)。这启发我们不断缩小可能区间来得到最后的最小值位置。
所以我们可以 \(\operatorname{solve(l,r)}\) 来找到 \([l,r]\) 的最小值,我们把序列平均分为三段,\([l,s],[s+1,t],[t+1,r]\)。然后比较
列式子分析一下,记录中间区间的和为 \(sum\),三个区间的最小值分别为 \(m_1,m_2,m_3\)。
-
\(m_1\) 为区间最小值,那么 \(L=s\),\(R=s+m_3-\min(m_2,m_3)\),故此时 \(L\le R\)。
-
\(m_2\) 为区间最小值,那么 \(L=s-m_2+m_1\),\(R=s-m_2+m_3\),故此时 \(L\neq R\)。
-
\(m_3\) 为区间最小值,同理分析可得 \(L\ge R\)。
我们每次根据 \(L,R\) 的大小关系可以舍弃一个区间。当 \(L=R\) 的时候,我们舍弃中间区间。当 \(L<R\) 的时候我们舍去最右边区间。当 \(L>R\) 的时候,我们舍弃最左边区间。
因为存在舍弃中间区间的可能,这样子可能会造成序列不连续,但是经过讨论可以发现,中间区间如果在上一步被舍弃,代表最小值不在其中,那么后面的询问带上这个区间也不会造成影响。
如果区间长度等于 \(2\),可以用一次操作一和一次操作二来解决。
需要的操作 \(1\) 次数大概是 \(4\log_{\frac{3}{2}}10^6=136\) 次,符合题目要求。
AGC030C Coloring Torus
对于题目要求很神秘的题,我们可以尝试从感性角度理解一下题目,其实题目的要求就是对于每个数字相同的格子,要求他们所处的 "地位相同"(周围数字的可重集合相同)。所以相同数字的格子应该是比较对称的。
所以我们可以给出 \(k\le 500\) 的构造,就是第 \(i\) 行全填 \(i\)。
对于 \(k> 500\) 的情况,我们无法采取以上策略,因为会有若干数学无法填入了。
思考一下能否扩展,在 \(4\mid n\) 的时候,我们将更大的数间隔塞入。
1 5 1 5
2 6 2 6
3 7 3 7
4 8 4 8
对于 \(4\mid k\) 的情况,我们还是可以构造出来这么一个对称形状的。
对于 \(2\mid k,4 \nmid k\) 的情况,同一行内首尾相同会造成不满足要求。
同时当 \(k\) 是奇数,我们也无法完成。因为必然存在某一行无法被更大数间隔地塞入。局部结构大概是这样子地,
1 x 1 x
2 2 2 2
我们可以发现偶数列的 \(2\) 可以被 \(x\) 影响到,但是奇数列的 \(2\) 无法被 \(x\) 影响到。所以 \(2\) 的地位不对称。
考虑如何解决这个问题,我们要通过某种手段使得统一奇偶列。可以发现如果我们将原图旋转 \(45°\) 的话,原本和 \(x\) 在对角线的奇数列 \(2\) 就可以和 \(x\) 相邻了,并且偶数列的 \(2\) 还是保持相邻。而且对角线也正好保证了对称性。
先给出对角线的基本 \(k\le 500\) 构造。
当 \(k=6\) 的时候,大概是长这样子的,
1 2 3 4 5 6
2 3 4 5 6 1
3 4 5 6 1 2
4 5 1 6 2 3
5 6 1 2 3 4
6 1 2 3 4 5
尝试加入三个数,我们就按照对角线上交替放的原则来插入新数。
1 2 3 4 8 6
2 3 9 5 7 1
3 4 8 6 1 2
9 5 7 1 2 3
8 6 1 2 3 4
7 1 2 3 9 5
注意就是我们默认上三角矩阵加入新的数字就是从每个斜线的第一列开始加,然后对于下三角矩阵,为了符合要求,对于第 \(i\) 行,我们从 \(1+(i\bmod 2)\) 列开始加。
可以发现是符合要求的。发现只有 \(n\) 为偶数的时候,构造才符合要求,因此取 \(n=\lceil\frac{k}{4}\rceil\times 2\)。我们维护 \(2n-1\) 条对角线,然后不断插入新的数,最后还原成一个正方形即可。
其实还有一种构造很精妙,那就是 \(k\le 500\) 的时候 \(a_{i,j}=(i+j)\bmod n\)。对于 \(k\) 更大的情况进行调整。这样子保证了 \(a_{i,j}\) 相邻数字的一致性,不过很难想到。
ZROI2840.千年红
结论:dfs 走出的树上全是返祖边,bfs 走出的树上全是横叉边。
当 \(n,m\) 比较小的时候,可以直接 dfs 构造出来一组全是返祖边的树,然后一条边一条边的调整。
但是可以更快,我们发现如果 \(u\) 有 \(k\) 个祖先边 \(e_1~e_2~e_3...e_k\) 本来是连着 \(e_1\),如果调整到 \(e_{t+1}\) 的话,就会少 \(t\) 条返祖边。于是我们可以正好凑出 \(a\) 条返祖边,然后 bfs。或者直接对于每个点记录所有祖先边,对 dfn 排序,然后从根最后遍历一遍调整。
记录下所有祖先边再最后上调这步是关键。
P11189 「KDOI-10」水杯降温
两种操作顺序不影响的题,可以考虑先进行某种操作再进行另一种。其中第一个进行的操作必须使得第二个进行的操作正好有可行性。
考虑先进行子树加操作,最后进行链减。可以发现为了使得链减合法,必须满足 \(a'_u=\sum\limits_{v\in son_u}a'_v\),且叶子节点权值 \(\ge 0\)。这样子就和链减无关了,只需要考虑通过子树加来构造出满足上述条件的树。
设 \(val_u\) 表示 \(u\) 以及其祖先执行子树加 \(1\) 操作的次数。\(val\) 肯定有约束的,第一感觉应该是一些很复杂的等式守恒。其实由于可以对于本身加,所以这其实是一个很松的限制,满足对于 \(v\in son(u)\),\(val_u\le val_v\)。
下面就是列式子了,\(a_u+val_u=\sum\limits_{v\in son(u)}a_v+val_v\)。
只需要我们找到一组符合要求的 \(\{val_n\}\) 即可。可以从叶子节点来从下往上推导。
其中对于叶子节点有最终 \(\ge 0\) 的约束,所以有 \(a_u+val_u\ge 0\)。然后依据这个来往上推祖先。由此可以看出每一个满足条件的 \(val_u\) 应该都是一个范围。
我们从下到上解 \([l_u,r_u]\) 代表 \(val_u\) 的范围。在 \(val_u\ge 0,val_v\ge val_u\) 的约束下考虑 \(v\to u\)。对于第一个条件我们可以在解出范围之后对于 \(0\) 取 \(\max\) 即可。对于第二个条件发现 \(val_u\) 越小越容易满足,所以我们贪心地调整所有 \(val_v\) 为 \(l_v\)。那么 \(l_u=-a_u+\sum\limits_{v\in son(u)}a_v+l_v\)。对于上界就有点难搞了,因为约束要求的是 \(val_u\) 尽可能小,而我们想最大化。这里有两种思路:一种是二分 \(val_u\) 的取值。第二种是发现 \(val_v\) 的防缩方向是 \(r_v\) 或者 \(val_u\),直接枚举取 \(val_u\) 的个数然后解不等式即可。
其实顺着我自己的思路走应该也是可以做出这题的,首先数学化这个过程。
那么每个点就是 \(a_u+\sum\limits_{v\in anc(u)} add_v-\sum\limits_{v\in leaf(u)} del_v=0\)。一个很暴力的想法就是 \(O(n^3)\) 来解这个方程,但是时间复杂度不对并不意味着我们不能从这里继续推到。
仔细分析一下,其实是可以发现方程的个数是要小于未知数的个数的,所以我们要求解的应该是未知数的一个范围而不是具体的值!而且这个 \(add\) 和 \(del\) 比较不太统一,尤其是 \(del\) 只有叶子节点处会产生,这启发我们定一个变量,动另外一个变量。我们固定 \(add\),考虑 \(del\)。
这是因为 \(del\) 的约束性和特殊性远远强于 \(add\)。列出 \(del\) 的约束方程,\(del_u=\sum\limits_{v\in son(u)} del_v\)。将上面列出的方程代入进行消元可以得到 \(a_u+sum_u=\sum\limits_{v\in anc(u)} a_v+add_v\)。
这样子一来不仅可以很自然的得到和第一种做法相同的方程式子(至少我是没想到可以先进行某一操作再利用另一个操作来进行调整),而且还可以启发我们得到解应该是一个范围。
本题中询问的联通性都是只是和特殊边相关的,和非特殊边没有啥关系,可以直接看成一张只有特殊边构成的图。于是问题就变成了有一张隐藏的图,给定一些可能在图上的边判断它们是否在图上。下文也是按照把特殊边和非特殊边改成是否在图上来写的。
首先还是交互题老套路,我们要思考如果构造一个良好的初始状态使得可以很好地通过询问来获得一些有效信息。
从全局角度直接对于整个图操作很难下手,我们不妨从每条边单独开始思考。
因为询问的是联通性,一次询问能产生贡献只有在图原本联通且断开一条边后某次询问得到了不可达的时候才能产生贡献,也就是可以帮助我们分辨这条边是不是在图上。
如果图原本不联通,那么不管是否断开这条边都有可能得到不可达的回复。所以要求一是初始状态的图必须满足可以通过没有被断的边联通。
如果我们断掉一条边的时候得到的回复是可达,那么说明这条边在不在图上都是一个效果,也就无法分辨它到底在不在图上了,这引导我们思考这条边如果是未断开边的桥的时候才能产生贡献。要求二是初始状态必须通过连/断边快速使得某条边成为未断边中的一个桥。
通过以上两个要求,我们可以发现原图的一个生成树是满足这个初始状态要求的。
因为首先树是联通的,其次对于一条边 \((u,v)\) 我们只需要断开树上 \(u-v\) 路径上的任意一条边再连上 \((u,v)\) 就可以使得 \((u,v)\) 变成桥了。
下面是本题的实现方法。
首先,需要找到一颗生成树。
一个图的生成树可以通过持续断开在残余图上的非桥边来得到。于是我们枚举每条边如果不是桥我们就删去,剩下的就是一颗生成树了。注意:不在原图上的边也会被上述过程删掉。于是剩下的边就是在原图上的边(特殊边)构成的生成树了。
上述一步构造了一个良好的初始状态。
接下来只需要再次枚举每一条边 \((u,v)\),然后断开 \(u-v\) 路径上的某条边再连上 \((u,v)\) 判定 \((u,v)\) 是不是桥即可。
最后一个问题是如何判定一条边是不是桥,假设目前断开了一个桥 \((u,v)\),那么图分成了两个分别包含 \(u\) 和 \(v\) 的联通块,因为交互库不会根据本次操作来确定另一点 \(s\),所以单次询问可以看成是随机的, 各询问 \(u,v\) 十次即可。
P9731 [CEOI2023] Balance
先考虑 \(S=2\) 的做法,我们对于
对于 \(S\) 更大的做法,我们先做 \(S=2\) 然后分治下去。