Professional Documents
Culture Documents
7.23 CF训练题解
7.23 CF训练题解
7.23 CF训练题解
23 CF训练题解
BY 颜智瑶
A. Swaps in Permutation
题意
思路
我们将这个问题具象化成图。对于每对 产生一条连边,则m对下标具象化为由若干个联通块。
可以发现,在同一个联通块中出现的下标,可以通过若干次合法交换,得到任意的排列。
(举例说明)
因此,要让字典序最大,即让同一个联通块中下标所对应的数字降序排列,再在原数组对应位置修
改。采用 或 寻找联通块皆可。
联通块后的排序处理:
①最朴素的思想是分别记录每个联通块中的下标和对应 ,对 降序sort后按下标升序填入对应
位置。
(下标也可以直接计数)
②有一种更加简洁优美的处理方法是优先队列,把同联通块的值都放进祖先对应的优先队列里,遍
历数组时找出该下标祖先对应的队首即可。
和7.22晚上的E解法有异曲同工之妙。
B. Sequence Sorting
题意
给一个长为n的数组,每次可以选择一个x,并将数组中所有满足 的数移到数组头或数组
尾,求最少操作几次可以让数组单调不减。
思路
设移到数组头的元素中最大值为 ,移到数组尾的元素种最小值为 。
不难发现,为使数组有序,显然 。我们会:
因此,数组中没有发生移动的是一段连续的区间 。题目所求即这段连续区间长度最大值。
题目要找一段连续的、没有“插队”的数,可以套用dp的思维。当然,简单变量维护也是可以取代dp
数组的。
我们可以这样处理:对数组排序去重后,获得数组b。遍历数组b,如果发现“插队”数,连续区间清
空,重置成1;否则,就是dp转移,长度+1。dp[i]表示不需要移动的数字,那么对于第 位,ans = 不
重复元素总数-dp[i]。
最后的答案是所有ans里的最小值。
C. Coffee Break
题意
有n杯咖啡,每杯咖啡对应a[i]表示我想在每天工作的第几个时刻喝掉它。m是每天的工作时间,d
是两杯咖啡的间隔,求最少几天可以喝完所有咖啡。
思路
贪心解决即可,因为要求按读入顺序输出,所以要先对每杯咖啡标记编号。又因为每杯咖啡都要喝
的,肯定是时刻越早的尽可能往前排,来不及喝的增加一天总天数。所以我们按咖啡饮用时间排序,掏
出我们美丽的优先队列,记录已确定天数的最后一杯咖啡的时刻以及是第几天喝的,尝试在这杯咖啡后
再喝一杯咖啡。如果间隔大于d,则保存答案;否则,增加一天。再把新增的咖啡也放进优先队列,模拟
一遍过程即可。
D. Two Teams
题意
有n个队员排成一队,第i个人的能力值是a[i]。有两个教练在选拔队员,由一队教练优先。教练们每
次会在剩下的队员中挑出能力值最大的,并且把该队员当前左边k个人和右边k个人(不足k个则尽可能
选)也选进这个队伍,问最终每位队员的队伍分配情况。
思路
模拟题。
显然,取出剩下能力值最大只需将原数组排序,按能力值从大到小选人,遇到已经被选(已经记录
答案的)就跳过。唯一需要解决的问题就是如何以i为中心,向两边各取k个,并且将它删除。
一个很好的选择是方便逐个查询及删除的链表结构。采用L、R数组模拟双向链表,初始化后,每次
向左右遍历k个数,并将删除区间的左右结点连接,这样每个队员至多被访问一次,就可以在 的时
间内完成选队员和出队的维护。
有n个队员,第i个人可以用两个值表示:a[i]和b[i]。
有编号为0~59的60种算法,把第i个人的a[i]转换成一个60位二进制,若则二进制第j位为1,说明第i
个人掌握第j种算法,否则为0。当A掌握了一种B不会的算法,他就会觉得自己比B厉害。
现在要选拔若干队员(至少两名),如果有个人觉得自己比队内所有人都厉害,这就是个狂妄的
人,我们不欢迎这种人。
选拔队的能力是所有入选队员的b[i]之和。求选拔队能力最大值,且保证队内没有狂妄的人。
思路
首先,如果有多个人a[i]相同,那么众生平等,谁也不会鄙视谁,一定可以都选拔进来;
看数据范围,n<=7000,可以支持一个 的暴力。也就是说,发现重复出现的a[i],先把 加
入队伍,再向前查找,把所有不觉得自己很厉害的 加入,即把 的 也加入队伍。
sort(a + 1, a + 1 + n);
for (int i = 2; i <= n; ++i) {
if (a[i].first != a[i - 1].first) continue;
vis[i] = 1;
for (int j = 1; j < i; ++j) {
if ((a[i].first & a[j].first) == a[j].first) vis[j] = 1;
}
}