CF Round 982(Div 2)

游记

还是VP
口胡了ABCD的做法,然后C假了
打代码其实挺难的

题解

A

反复观看样例可知,如果两个开关状态不一样灯泡开,否则灯泡关
如果要灯泡开着的尽可能少,那么相同状态的配对尽可能多
此时就是\(0\)\(0\)配对,\(1\)\(1\)配对,
如果有落单的\(0\)必定有落单的\(1\),最多凑\(1\)
没有就是\(0\)
反之要灯泡开得多,那么\(0\)\(1\)的配对尽可能多
此时答案就是min(cnt[0],cnt[1])
其中cnt[i]就是满足\(a_j=i\)\(j\)的个数

B

如果从数组中删掉\(k\),那么数组就会变成两半
这两半中,左半边不管怎么分,各部分中位数必然小于\(k\)
因为最大数都小于\(k\)了中位数肯定小于最大数小于\(k\)
同理右半边不管怎么分,各部分中位数必然大于\(k\)
那如果各部分中位数组成的数组,这个中位数如果是\(k\)的话
其实只需要两边划分出相同的段数即可
如果左右两边都是偶数个元素,那就各分成两个奇数的段
此时\(k\)为奇数
否则两边都不用动,就一整段,此时\(k\)为偶数
唯一需要考虑的就是一半边为空的情况
此时只有另一半边也为空才行
也就是无解判断:
\(k=1\)\(k=n\),且\(n\not=1\)时无解
如果\(n=1\)那就得特判出去,很简单

C

对于能否构成三角形来说,
如果两个小边加起来大于最大的边,那必然可以构成三角形
所以如果钦定\(a_i\)为最大值
首先大于\(a_i\)的要被赋成\(a_i\)
然后如果\(\exists j,k,a_j\leq \frac{a_i}{2},a_k\leq \frac{a_i}{2}\)
那么显然\(a_j+a_k\leq a_i\)就寄了
所以至多存在唯一的\(j,a_j\leq \frac{a_i}{2}\)
然后就是对\(a\)排个序先,
枚举每个\(a_i\),找到值域在\([\frac{a_i}{2},a_i]\)的最大下标区间
两个下标lower_bound()/upper_bound()一下即可
不在这个区间范围的都要改成\(a_i\)
取改的次数的最小值即可,这个显然可以\(O(1)\)算出来
枚举\(a_i\)二分的复杂度\(O(n\log n)\)
排序时间复杂度\(O(n\log n)\)
总时间复杂度\(O(n\log n)\)
写法在下取整和二分的时候挺麻烦的,有些细节要注意

D

首先,如果\(i\geq j\),必然有\(p_i\geq p_j\)
其次,这棵树切开\(0\)以后必然是若干条链
这样的话首先考虑同一层的节点\(i\)\(j\)
\(c_i\)为切掉\(0\)以后的链顶编号
如果\(c_i+1<c_j\),并且\(i,j\)同层
那么中间空着的这么几条链必然不可能连上任何大于\(j\)的节点
否则\(k>j,p_k<p_j\)显然会寄
也就是说,可用的链顶\(c_i\)这个集合的元素只出不进
那么就直接找链顶有多少即可
显然由于BFS序的关系,\(c_i\in [1,l-1],p_l=1\)
也就是说我们直接找到\(l\)即可求出\(c\)
然后对于每个\(i\),如果确定了\(i\)对应的链顶\(c_i\)
直接问\(c_i+1\)\(i+1\)的关系
如果\(c_i+1\not=c_{i+1}\)直接把\(c_i+1\)扔出去
如果找到了对应的\(c_i\)维护\(c_i\)这条链底下编号最大的元素更新即可
注意如果只剩下了\(l-1\)那就不用问了

posted @ 2024-11-07 20:28  2K22  阅读(5)  评论(0编辑  收藏  举报