2022 寒假测试 8 解析
2022 年寒假第 8 次测试解析。
T1 「JOISC 2016 Day 2」女装大佬
原题为 JOISC 2016 Day2 T3 「トイレ」。
题面
题面
题目描述
题目译自 JOISC 2016 Day2 T3 「トイレ」
题面魔改原因:原题是男选手太多所以要借用女厕所 译者表示无法接受
IOI 的队服有两种,一种男装,一种是女装。然而很遗憾,所有参赛队伍中并没有女生,只有女装大佬。现在 IOI 设置了两个发放点,一个点只发放男装,另一个点只发放女装。
现在,所有队伍总共个参赛队员,他们排成一列来领取队服,领取队服的规则如下:
- 当前队首是女装大佬,如果领取女装的地方是空的,那么他就会领取女装,否则如果领取男装的地方是空的,他会去领取男装;
- 当前队首是正常男生,如果领取男装的地方是空的,那么他会领取男装,否则如果女装位空着,他就发挥绅♂士精神,给身后的最前面的女装大佬让位,让他先领取女装。
已知任意一个人领取队服都需要一分钟的时间,现在你需要重排所有人的顺序,使他们在分钟内领完队服 。
定义一个人的 Dark 值为:在重排队伍之前在他后面,且重排队伍之后在他前面的人的数量。
你现在需要找出重排后整个队伍最大的 Dark 值至少为多少。
输入格式
第一行为一个数
,为领完队服的时限,同时 代表着总领队服人数,需要注意的是,这不意味着正常男生和女装大佬刚好各占 个;
第二行为一个数,指队伍共有 种;
之后的行,第 行包括一个字符串和一个数字,描述该队伍的组成,其中 M
表示正常男生,F
表示女装大佬,之后的一个数字,表示该字符串连续出现了几次。所有字符串长度乘上出现次数的和等于。
输出格式
一个数,表示重排后最大 Dark 值的最小值,如果在
分钟内不能完成领取队服的任务,输出 。
思路
(这里的说法是基于原题 “トイレ” 的背景 —— 撤硕分配来说的)
首先我们需要判断哪个序列是一个可行的方案。
我们虽然可以从头开始模拟,但是这样需要耗费的时间实在是太多了。
因此,我们考虑从最后一分钟倒推。
既然我们有两个撤硕,总共
那么我们看一下最后一分钟。
如果最后一分钟在队列里面等待的是两个男生,那么他们已经可以商量谁去女厕所了。
所以我们可以猜想,男的必须尽量靠前。
我们尝试将每一个 F
当做 M
当做
我们需要确保所有人加起来不大于 0,即最多有
我们还需要确保每一段后缀和都不大于 1。自己用手推算一下的话,那么我们可以轻易发现,一旦有后缀和超过 1 的情况的话,那么最后肯定有两个(或更多)男生需要决定谁进女厕所。
我们可以选择二分让队尾多少个男生去往队头,也可以统计整个序列中后缀和最大值之后再 + 1。
代码
100 分代码:
1 | #include<bits/stdc++.h> |
一发 36 分的 Java8 代码:
Java8
1 | //import java.util.Arrays; |
T2 【常中 20180812T3】 test
题面
题面
题目背景
Tom 在学写动态树,但是做题时过了样例,提交 RE。Tom 抓住 Jerry 要他写个暴力来对拍。Jerry 觉得这任务太简单了,就让你来完成一下。
题目描述
有一棵
个节点的树,初始时根节点为 1。现在要支持如下操作 ——
- 将某节点设置为根;
- 改变某节点权值;
- 询问以某节点为根的子树内节点权值之和;
- 询问以某两点为端点的链上的节点权值之和。
输入格式
第一行两个正整数
和 ,表示树的节点数和操作个数。
接着行每行两个整数 和 ,表示有连接 和 的一条边。
随后一行个正整数,表示每个点的初始权值。
之后行每行格式如下:
首先一个范围为的正整数,表示该操作类型。
对于 1 操作,之后一个正整数,表示将 节点设置为根。
对于 2 操作,之后两个正整数和 ,表示将 节点的权值改为 。
对于 3 操作,之后一个正整数,表示询问以 为根的子树内节点权值之和。
对于 4 操作,之后两个正整数和 ,表示询问以 和 为端点的链上的节点权值之和。
输出格式
对于每个操作 3 和操作 4,输出一行一个整数表示询问的答案。
思路
根据题目所给出的要求,我们可以使用 LCT 做这道题。
但是 LCT 太难了我不会啊 QwQ
所以我们考虑退而求其次,使用换根树剖来做。
实测可行。
换根操作只会影响作用于一个节点子树上的操作,比如子树加,子树求和等等。
巧了,这里就有一个。
那就有点头疼。
我们根据要需要操作的节点
x==rt
这种情况明显很简单 —— 就是整棵树。lca(x,rt)!=x
这样我们可以知道现在的根 没有在 的子树里,此时 的子树与根为 1 时的子树无异,可以直接操作。lca(x,rt)==x
这时候我们发现 在 的子树里面。
此时, 的子树就会发生很大的改变。原先 的子树包含 的那个儿子现在成为了 的父亲,而其他儿子不变。原先为 父亲的节点成为了 的其中一个儿子,原先除其子树以外的节点都成为了其子树。
我们称这个子树包含 的儿子为 。
现在 的子树是 这两段连续的区间。
我们可以考虑对这两段区间分别操作,也可以选择对整棵树操作以后在减去中间的那一块 er。
代码
100 分代码:
1 | #include<bits/stdc++.h> |
re 的 Java8 代码(求调):
Java8
1 | import java.util.Arrays; |
T3 【20180819 省队班】 取数字
题面
题面
题目描述
给定
个整数 ,你需要从中选取若干个数,使得它们的和是 的倍数。问有多少种方案。有多个询问,每次询问一个的 对应的答案。
输入格式
第一行两个正整数
, ,分别表示整数的数量和询问的数量。
第二行个整数 。
接下来行,每行表示一个 。
输出格式
对于每个询问,输出一行答案
。
思路
这道题是个背包计数的问题,背包的容量是模 m 循环的。
记 f[i][j]
表示考虑了前
我们注意到 m 很小,而 n 很大,也就是说有很多重复的值,那么我们考虑设计一个下标为 dp[m][m]
的 DP 方法,每次考虑一类数。
假设第 k[i]
个,我们的转移是:
注意到 dp[i-1][j]
的贡献。写成伪代码就是:
1 | for h : [0, k[i]] |
然后我们再递推 dp[i][j]
,把
总复杂度
代码
100 分代码:
1 | #include<bits/stdc++.h> |
re 的 Java8 代码(求调):
Java8
1 | import java.util.Arrays; |
未找到相关的 Issues 进行评论
请联系 @KaiserWilheim 初始化创建