Codeforces Global Round 9题解

Contest链接

CF1375C Element Extermination

题意:给定一个排列\(a\),每次操作你可以选定一个\(i\),满足\(a_i < a_{i+1}\),然后删除\(a_i\)或者\(a_{i+1}\)。问最后能否使排列仅剩下数字1。\(\sum n \leq 3 \times 10^5\)

题解:大胆猜一波结论:存在方案当且仅当:\(a_1 < a_n\)。事实也确实是这样。为什么呢?

考虑\(a_1 >a_n\)时,我们肯定不希望排列最后只剩下它们两个数,因此需要将\(a_1\)变小或将\(a_n\)变大。但无论我们怎么操作,\(a_1\)是不会降的,\(a_n\)也是不会升的(这里的\(a_1\)\(a_n\)指的是序列首位的元素)。

CF1375D Replace by MEX

题意:给一个序列\(A\),每次操作可以选定一个位置\(p\),令\(a_p=\)这个序列的\(mex\)。你需要进行若干次操作,使得这个序列单调不降。操作次数不能超过\(2n\)

\(n \leq 1000,a_i \in [0,n]\)

题解:为方便起见,我们将序列按\(0\)\(n-1\)编号。考虑能否将序列还原为\(0\)\(n-1\)的序列。

当序列的\(mex\)小于\(n\)时,我们令\(p=mex\);否则,令\(p\)为任意一个\(a_i \neq i\)的位置\(i\)。这样做,操作次数的上界为\(1.5n\)。下面是一个简单的证明:

考虑当\(mex=n\)时,整个序列是\([0,n-1]\)的一个排列。我们做完一次操作后,序列的\(mex\)就变为了\(a_p\),令\(a_{a_p}=a_p\)后,序列的\(mex\)又变成了原来的\(a_{a_p}\)。那么要使\(mex=n\)的出现次数最多,显然形如\(0,2,1,4,3,\cdots\)这样有很多"2-cycle"的排列是最毒瘤的,每做2次,序列的\(mex\)就会变成\(n\)

直接模拟即可。

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

CF1375E Inversion SwapSort

题意:给定一个序列\(A\),长度为\(n\)。我们记录下序列所有逆序对的下标\(u_i,v_i\)。你需要给所有的\({u_i,v_i}\)指定一个顺序,每次交换\(a_{u_i},a_{v_i}\),使得所有操作完成后的序列单调不降。

\(n \leq 1000,a_i \leq 10^9\)

题解:先考虑对于一个排列如何求解。设\(p_{a_i}=i\)

我们尝试从后往前逐位确定答案。考虑当前序列的最后一位\(n\),它想成为\(n\),那么\(a_n\)必须在与\(n\)有关的最后一次操作中被换到位置\(n\)。所以,我们只需要依次进行如下的操作:(\(p_{a_{i+1}},n\)),(\(p_{a_{i+2}},n\)),\(\cdots\),(\(p_{n},n\))即可。剩下的问题就是一个\(n-1\)的子问题了。

那么对于序列的情况也就很简单了:将所有元素按\(a_i\)为第一关键字,\(i\)为第二关键字排序,化成排列的问题即可。

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

CF1375F Integer Game

题意:这是一道交互题

有三堆石子,个数分别为\(a,b,c\)。游戏的规则如下:

  • 先手每次给定一个数\(k\),后手需要给这三堆石子的某一堆的个数加上\(k\)
  • 后手不能连续对同一堆石子进行操作。
  • 当存在两堆石子个数相等时,先手胜;当回合数超过1000时,后手胜。

你可以自行决定当先手还是后手。

\(a,b,c \leq 10^9,k \leq 10^{12}\)

题解:考虑什么情况下后手无法操作:

  • 设当前石子个数为\(a,b,c\),且\(a<b<c\),上一次操作的是\(c\)这堆石子。
  • 那么当\(a,b,c\)形成等差数列时,后手就无法操作了。

因此,这是一个先手必胜的游戏。我们只需要构造一种方案,使它到达这种状态即可。

还是令\(a<b<c\),那么我们先强制让操作后的那对石子个数最大。显然令\(k=c-a\)即可。

现在,上次操作的一定是\(c\),那么我们稍微计算一下,令\(k=2c-a-b\),就能让得到的\(a,b,c\)成为一个等差数列。并且由于\(a+k>c\),所以操作的那堆石子在操作完成后一定是个数最多的。

CF1375G Tree Modification

题意:给定一棵\(n\)个点的树,一次操作,你可以选定三个点\(a,b,c\),要求\(a\)\(b\)相邻,\(b\)\(c\)相邻,然后进行如下操作:

  • 所有与\(a\)相邻的节点和\(c\)连边;
  • 断掉连接\(a\)与其所有相邻节点的边;
  • \(a\)\(c\)连边。

你需要最小化操作次数,使得这棵树仅存在一个节点度数为\(n-1\),其他节点的度数都为\(1\)。不需要输出方案。

\(n \leq 2 \times 10^5\)

题解:由于树无环,我们可以将其看做一个二分图,并将其黑白染色。那么目标状态显然是只有一个黑或白点。考虑一次操作对黑白点个数的影响。我们设\(c\)是黑色的。

对于所有与\(a\)相邻的节点及其子树内的点,颜色不变;只有节点\(a\)的颜色改变了。

因此,一次操作只会使黑或白点个数变化1。那么答案显然就是\(min(cnt_{white},cnt_{black})-1\)

直接DFS一遍就好了。

CF1375H Set Merging

题意:给定一个长度为\(n\)的排列\(a\),初始的时候存在\(n\)个集合,第\(i\)个集合为{\(a_i\)}如果两个已经存在的集合\(X,Y\)满足 \(X_{max}<Y_{min}\),则可以添加一个新的集合\(S=X\cup Y\),称这为一次合并操作。

你可以进行若干次合并,但是需要保证总的集合数量不超过\(2.2\times 10^6\)

现在有\(q\)个限制,每个限制包含一段区间[l,r],需要保证操作完后的所有集合中存在至少一个集合等于{\(a_i|i\in [l,r]\)}。

\(n \leq 2^{12},q\leq 2^{16}\)

题解:发现\(n\sqrt{q} \approx 2.2\times 10^6\),我们考虑往分块的角度想。不愧是Ynoi

我们将值域\([1,n]\)分块。设块大小为\(S\)。发现一个很优秀的性质:如果我们把\([1,n]\)按值域划分成\(\frac{n}{S}\)个子序列,那么对于每个询问\([l,r]\),我们也将其划分为\(\frac{n}{S}\)段,那么每一段都是序列\([1,n]\)划分出来的对应的那个段的连续子序列。比如原序列为\(5,3,1,8,9,7,2,4,6\),我们将其划分为{\(3,1,2\)},{\(5,4,6\)},{\(8,9,7\)}三段。那么对于询问\([2,6]\),我们只需要将其划分为{\(3,1\)},{},{\(8,9,7\)}三段。这三段都是原序列分出来的三个序列的连续子序列。一个块的连续子序列个数是\(\frac{S\times (S-1)}{2}\),那么总个数就是\(n\sqrt{n}\)的。我们将这些连续子序列全都求出来,然后对于每个询问,直接merge它对应的这\(\frac{n}{S}\)个连续子序列就行了。

那么如何求出一个块内的所有连续子序列呢?我们考虑以权值大小来进行分治。假设我们要求出序列\(5,3,1,8,9,7,2,4,6\)的所有连续子序列,当前已经求出了\(5,3,1,2,4\)\(8,9,7,6\)的所有连续子序列,合并时,由于这两个序列与原序列的关系依然是子序列的关系,那么我们就只需要类似归并排序那样做就行,只不过因为要求出所有的连续子序列,我们可以枚举整个序列的左右端点,把两个序列的元素的位置信息扔进两个vector里,查一下分别的前驱和后继,然后直接合并即可。比如我们现在要得到\(1,8,9,7,2\)这一段,我们就分别找出\(1,2\)\(8,9,7\)这两个子序列,然后直接merge。

\(cnt=O(n\sqrt{q})\),时间复杂度大概是\(O((n+q)\sqrt{n})\)

posted @ 2020-07-09 11:55  Purple_wzy  阅读(189)  评论(0编辑  收藏  举报