构造题学习笔记
CF1110E Magic Stones
题意:
一次操作选择\(1<i<n\),使\(c_i\)变为\(c_i'\),\(c_i'=c_{i+1}+c_{i-1}-c_i\)
是否能做若干次操作,使每个\(c_i\)和\(t_i\)相等?
题解:
可以发现经过一次操作之后,会导致和两边的差交换位置,所以这个变化中数列差分的集合我们发现是不会变的,所以我们就有了一个方法来判断是否:判断差分集合一不一致。
我们可以先特判完首尾,然后把两个的差分数组都求出来,然后排序完判断是否一样即可。
hdu7393
题意:
有\(n\)个人,每个人头上有个\(1..m\)之间中的某个数字,每个人都能看到其他所有人的数字,但是看不到自己的。求一种整体策略,使得至少\(floor(n/m)\)个人猜对自己头上的数字
题解:
我们可以知道这\(n\)个数的和取余\(m\)的数一定是在\(0..m-1\)之间,不妨我们根据这个分类来达到目的,具体的说,对于第\(i\)个数,我们可以设总和取余\(m\)为\(i\mod m\) ,然后据此求出此数,这样每\(m\)个数中就会有一个是设的取余正确也就是说我们求出的数也是正确。
于是达到目的。
启发
我们采用了互斥的思想,考虑情况使得几个数之间正确的概率互斥,借此使得猜对刚好\(floor(n/m)\)个数,这样可以比乱猜的概率稳定,使得我们通过此题
互斥的思想例如,\(P(A)=0.5\),\(P(B)=0.5\),如果要保证\(P(A和B至少有一个)=1\),那么\(P(A和B都有)\)就必须是\(0\)
CF1672E
题意:
给你n个单词,每个单词有一个长度\(l[i]\),你最多可以查询\(n+30\)次,每次给出一个宽度\(w\),交互器会告诉你需要多少行宽度为\(w\)才可以放下所有单词,要求找到使用面积最小的方案,其中一行内放\(l[1]..l[k]\)需要的长度至少是\(l[1]+l[2]+..+l[k]+(k-1)\)。
题解:
首先我们显然可以通过二分这个 \(w\) 来得出总长度 \(L\) (此时 \(h=1\) ),不妨设这个 \(w\) 为 \(w_1\),由于这一行是每一个都间隔一个空格,所以 \(w_1=L+n-1\) 。
得出来 \(w_1\) 了,接下来我们该怎么问?假设我们问 \(w_k\),获得了答案 \(h_k\) ,考虑总面积 \(w_kh_k\) 的最大最小值,因为只有当得到的答案小于 \(w_1\) 时才会对答案有贡献,所以我们最大值就是 \(w_1\) ;最小值的情况为每一行的末尾都没有空格,也就是说相对于说总面积为 \(w_1-h+1\),所以最小值为\(w_1-h+1\)。
所以我们每次问得到的面积区间为:\([w_1-h+1,w_1]\),这让我们联想到了啥?这个区间除以\(h\)的值是\(w_k\),而可以由区间长度得知\(w_1\)除以\(h\)后的向下取整和\(w_k\)相等。
所以啊,所有可能会有贡献的\(w_k\)都等于\(\lfloor \frac{w_1}{h}\rfloor\),所以我们只需枚举\(h\)便可以把所有有可能有贡献的\(w_k\)都询问一遍。
总询问次数为\(log n+n<n+30\)。
CF1896G
题意:
这是一道交互题。
有 \(n^2\) 个人,每个人有一个跑步速度,保证任意两人的速度互不相同。
每次你可以询问互不相同的 \(n\) 个人,交互库会告诉你他们中跑得最快的人是谁。
请在 \(2n^2-2n+1\) 次询问内求出速度前 \(n^2-n+1\) 快的人的排名顺序,并输出答案。
多组数据,\(T\le 10^4,\ n\le 20,\ \sum n^3 \le 3\times 10^5\)。交互库自适应。
题解:
非常好的交互题。
(下面的最大值当然指的是位置)。
首先我们先给这个 \(n^2\) 长度的序列分成 \(n\) 个长度为 \(n\) 的块,然后我们创造出来 \(n\) 个集合,称为“块集合”,先存下这 \(n\) 个块里的每一个数,我们询问 \(n\) 次,可以得到这 \(n\) 个块中每一块内的最大值。
把这 \(n\) 个最大值从对应的块集合中提走,同时我们再创造一个集合,用来把这 \(n\) 个块中的最大值都存起来,这个集合至关重要,我们每次排序的数都是从这里提走的,不妨先称它为”主集合“。
显然,现在主集合中的最大值就是整个序列的最大值,对主集合做一次询问后,我们可以得到整个序列的最大值,现在我们得到最大值的我们十分开心,还想得到次大值,该怎么办?
显然刚刚得到的最大值已经没有用了,我们把它从主集合中删去,那么我们的次大值在哪里呢,它有可能出现在主集合剩下的数中,也有可能出现在最大值原先所在的块集合中,不可能出现在别的块集合中(因为别的块集合中原先被提走的最大值比里面每个元素都大)。
不如考虑把最大值原先所在的块集合中目前的最大值补到主集合中,这样我们便可以查询主集合来得到次大值,但是我们要查的块集合中因为被提走了元素,现在只剩下 \(n-1\) 个元素,我们该咋办?不妨和别的块集合里的任一一个数来一同询问。
嗯?补齐的做法为什么是正确的?因为别的元素不可能是次大值,即使我们询问的到的最大值是别的块集合中,只能说明目前块集合的数太劣了,本来就不可能成为次大值,而查到的别的块集合的数补到主集合中也一定会比真正的次大值要小。
ok,把查询所得的最大值补齐到主集合中,删去它在块集合中的位置,现在主集合又变为了 \(n\) 个元素,然后再询问主集合的最大值,得到次大值。
相信经过我们对次大值的处理,你应该体会出了后面的“次次大值”,“次次次大值”等等的处理方法与次大值的类似,总结一下就是以下两次询问。
- 把上次提走的值原来所在的块集合和别的块集合的若干数一同询问得到一个值,提走这个值。
- 把得到的这个值放入主集合并询问最大值,提走这个最大值放入当前答案序列的下一位。
就这样一直操作直到询问出答案序列里有 \(n^2−n+1\) 个人,那么我们的询问次数又是如何呢,刚开始进行 \(n\) 次询问,接着询问出最大值,然后每次对剩下的 \(n^2-n\) 个人每个人进行两次询问,一共是 \(n+1+2(n^2-n)=2n^2-n+1\) 次询问。
啊这……答案已经那么接近了,可是还是不对呀,整整差了 \(n\) 次询问呢。
好的,仔细分析我们漏掉了哪里,啊,对了,我们每回补充主集合都会从块集合中拿走一个数,这样一直提啊提啊,我们的块集合难免会被提到只剩下一个数或零个数,这时我们的第一次询问就可以免了(一个数时直接提走,零个数时从别的块中提走)。
但是我们可能会出现不平衡的情况。这样免的次数就边的少,该怎么办?我们只需在零个数时提走那些剩下数多的块集合即可,这样就可以尽可能保持平衡,分析可知,这样使得我们至少可以免了 \(n\) 次的询问次数。
综上,询问次数为 \(2n^2-2n+1\) 次,符合题意。
CF1270G
题意:
给你\(n\)个整数\(a_1 \,,a_2 \dots a_n\),第\(i\)个整数\(a_i\)满足\(i-n\le a_i \le i-1\).
找到一个这些整数的一个非空子集,使得它们的和为0。可以证明在给出的条件下一定存在这样的子集。如果有多个子集满足条件,输出其中一个。
题解:
要是不加上数据范围,这就是一个npc问题,但是我们现在有了数据范围,就可以来搞一些事情了。
不妨我们先把数列变一种形式,首先由于\(i-n\le a_i \le i-1\),所以可以知道 \(i-a_i\) 的数据范围,为\(1\leq i-a_i\leq n\),嗯~很美丽。
那么和为0的子集在 \(i-a_i\) 这种情况下又是长啥样子呢?可以知道非空子集和为0即\(\sum_{i=1}^{k}a_{b_k}=0\),来变化一下形式:
所以:
这就是说变换完之后相加的和与下标相加的和相等时符合条件。
这该如何实现呢?
我们可以建立一个有 \(n\) 个点的图,把 \(i\) 向 \(i-a_i\) 连一条有向边,这样建立出来的图如果形成了一个环,如此的\(i\)的和即是所有点乘上各自的出度,如此的\(i-a_i\)的和就是所有点乘上各自的入度,这样一个环的两个和可以证明是相等的,于是我们就得到了一个宝藏般的发现:发现环等同于发现了和为0的非空子集。

浙公网安备 33010602011771号