新年的破栈
from wyx528
算法一
容易发现,每次可能的操作不会超过 3 种,因此只要在需要决策的时候暴力枚举其中的一种即可,指数级复杂度,可以得到 20 分。
算法二
由于要求字典序最小,所以必然要把尽可能小的数提前出栈,更特殊地,一定会把最小的数最先出栈。
当最小的元素出栈时,记栈底元素为
可以发现,只要重复这个贪心过程即可取得最优解。使用朴素算法,选取未进栈元素最小值的时间复杂度为
算法三
使用堆或者平衡树来优化算法二中选取未进栈元素最小值的时间复杂度,使之降为
算法四
实际上,我们可以发现,每次选取未进栈元素最小值时,所涉及的决策范围必然是
新年的网警
from sevenkplus
题解 from jiry_2
算法一
可以发现每一个人第一次听到谣言的时间实际上就是发起人到达这个人的最短路径长度(假设边权都是
我们不放假设
于是我们可以把这
时间复杂度
算法二
我们可以发现,一个谣言发起人
- 他是大老师(在群里面只认识一个人)。
- 他认识大老师 (即认识一个满足条件 1 的人)。
- 存在一个人
使得 和 认识的人是完全相同的(这时忽略 和 的认识关系)。
首先这三个条件的充分性显然,考虑证明它的必要性。
假设存在两个人
- 他们至少有一个共同认识的人
,那么为了让 听到谣言的时间一样, 和 发起谣言的时间必定相同,假设这个时间是 。同时由假设,存在一个人 ,他恰好被两个人中的一个人认识,此时 两次听到谣言的时间必定不相同(一次是 ,一次必定大于 ),矛盾。 - 他们没有共同认识的人。那么假设
是在 时刻散布的谣言, 是在 时刻散布的谣言。考虑 到 的一条最短路,那么这条最短路的长度必定大于 (我们假设长度是 )。考虑最短路上离 最近的点是 ,离 最近的点是 ,为了让 两次听到谣言的时间相同,那么就有 和 。这个方程一定是无解的(因为 ),矛盾。
于是这个结论就得到了证明。因为条件 1 和 2 都很好判断,所以接下来只考虑条件 3。
我们可以枚举每一对人
期望得分
算法三
算法二的瓶颈在于枚举每一对人,而实际上需要忽略
这样时间复杂度就变成了
比赛的时候好像有人作死把哈希的模设成了
新年的繁荣
from Rating_Jia_Su_Qi
算法一
对于 subtask1,直接把完全图建出来跑 kruskal 算法就好啦。
时间复杂度
算法二
对于 subtask2,依然把完全图建出来,但是我们可以跑 prim 算法。
有人说我只会 kruskal 怎么办!可以发现 kruskal 算法的瓶颈在于排序,注意到边长不会超过
时间复杂度
算法三
对于 subtask3,点权只有两种
时间复杂度
算法四
对于 subtask4,考虑 kruskal 算法,我们可以发现如果选了某个点连出去的最大边肯定是可行的,由于
时间复杂度
算法五
对于 subtask5,顺着刚才的思路,如果
时间复杂度
算法六
来考虑一下普通的最大生成树除了 kruskal 和 prim 还有什么算法,既然选择最大边是对的,那么我们可以对于每个点选择最大边连好,缩完联通块,然后再对于每个联通块选择最大边继续缩!缩了
那么现在的问题就是这样,有
如果把
可以发现之前的合并以后每个点代表着它的子集,于是可以把 trie 改成子集和变换,关于子集和变换可以看吕凯风学长的2015年国家集训队论文《集合幂级数的性质与应用及其快速算法》。复杂度和 trie 相同。
时间复杂度
算法七
这个算法赛前并没有出题人/验题人/出题火车想到,但在考场上 BillXu2000 首先想到了这个算法,遗憾的是,他开小了数组所以没能A掉,另外一位参赛选手 Yemengmeng 也想到并使用这个算法A掉了本题。
首先我们使用算法四的思想去重,接着我们从大往小枚举边权
求每个点所在联通块以及合并这些联通块可以使用并查集维护,这样算法复杂度就是
具体可以去看代码:http://uoj.ac/submission/48502
算法八
最大生成树算法就是个垃圾!我们抛掉不要!这个算法一点都不玄学!接下来就让我们看看玄学算法。
我们依然是不断地合并联通块,不过现在是按照二进制位从高到低,对于每一个联通块我们都维护一个 trie,比如当前考虑第
这个算法比较玄学,复杂度我也不会算,实际运行起来还是很快的。
时间复杂度
具体可以去看的代码:http://uoj.ac/submission/48529
这个算法相比前面的算法优越之处在于他的时空复杂度在一定程度上不严格依赖于
新年的腮雷
from saffah
一句话题解:二分答案+逆向思维。想看AC算法请直接跳到算法九。
算法一
写一个最裸的大暴力(枚举每次选哪
算法二
五万两秒的范围,一看就是不必在意常数的两个log。
对于
看到“最大值最小”第一个想到的当然是二分答案了。为了解决“是否能使最大的和不超过
使用很多数据结构(比如multiset)都可以在
算法三
上面的算法其实做麻烦了,而且“任意顺序”这个也太随意了。我们把“任意顺序”换成“从大到小的顺序”,最终可以得出:只需将
时间复杂度
算法四
对于所有的
由于
策略是显然的。设
时间复杂度
算法五
上面的算法其实做麻烦了,而且“任选一个”这个也太随意了。我们把“任选一个”换成“选一个最大的”。这样无论二分出的是什么答案,拆分的策略(或者说,拆分树)都是一样的。所以只需令
时间复杂度
算法六
对于
设
如果
否则,不妨设
无论如何,总代价都不会变大,所以每次可以选择最小的两个合并。
时间复杂度
但是如果你只写了子任务4的程序,可以顺便通过子任务6和7,获得15分。
算法七
威力的设定总是让人们摸不着头脑。
我们定义威力为
这样定义的原因是,对于“理想的合并”情况(即所有的
直接输出这个数是不对的。例如,考虑
不过在
总之这样的乱搞可以过掉子任务4567,获得24分。
算法八
把以上各种乱搞合起来可以通过前7个子任务,获得72分。
(以及我也不知道有什么奇怪的算法,所以放了一点
算法九
终于开始说正解了。
还是二分答案。设当前答案为
还是逆向思维。问题转化为:是否存在一种拆分方案,能够从一个
我们考虑问题:给出猴腮雷的集合
对于一般的问题
如果
否则,如果
否则,设
如果
如果
正确性:
对于
对于
时间效率:
使用multiset维护两个集合,就可以
总的时间复杂度是
vfk:“好像很帅的样子”
后记
这道题的灵感来自于清华集训2015的King一题,其中有一个测试点需要解决这个问题的
而且,这道题最初的模样并不是保证
本来这道题是我想放到某个NOIP模拟赛里面的,但是想来感觉有点意思,就推荐给了vfk,然后vfk一开始也表示不太会……嗯,幸亏没有扔到NOIP模拟赛里面。
以及,为什么“为了方便,不必输出方案”呢?
因为输出方案实在实在是太太太太麻烦了。有多麻烦呢?标程我写了1.2k,输出方案的话估计至少要翻一番了吧。这道题的亮点在于二分答案和逆向思维,所以强行增加代码量也不是什么好事。
具体的方法就是要在上面的过程中再把分割树全部建出来,我想大家应该都会。
那么,就这样。
新年的贺电
from ppfdd,题目是 vfleaking 造的,题解也是 vfleaking 写的。
题意是要你实现一个传输协议,发送方发送一个 map<unsigned, unsigned>,使得接收方可以查询 map 里的值,且传输的长度要尽量短。
算法一
注意到
就直接把键和值编码发过去就行了。需要
可以获得
算法二
对于 30% 的数据,
这种情况下我们可以传 “键为
需要
可以获得
算法三
我想把算法一二贴在一起!
题目没给数据类型?!?!
由于接收方并不能特判数据类型,所以传 map 的时候需要加额外的 bit 来表示数据类型。(然后算法一就挂了)
没关系,我们可以判传的信息的长度对吧,就可以知道数据类型了。
可以获得
算法四
你可以使用哈希!
假设你有一个哈希函数,能把键分别映射到
好,那么怎么找这个哈希函数呢?
考虑直接随机,随机直到可以放进去,然后把随机次数传过去。
只用传一个随机次数,长度一看就很短。
所以!这样就可以…………………………获得 0 分了。
假设是要将
算法五
算法四是个很好的思路。仔细思考可以发现我们并不需要哈希一步到位。
我们可以考虑先通过不断随机哈希函数把键值对均匀分成两组,把随机的次数传过去,再递归每一组继续分割。只要发送方和接收方约定好随机哈希函数的随机方式就可以保证双方使用的是同样的哈希函数。
把
至于长度(不算传值的长度),大概是
可以获得 50~80 分。
道理我都懂,但是为什么我的输出这么长
你是不是用了定长的编码……
每次要输出次数的时候,你可以先设定一个初始长度
本题中我们要传的是随机次数,我们可以根据期望随机次数设定
算法六
结合一下算法四和算法五,在算法五进行递归的时候递归到
这是因为传次数的时候有一定的冗余……
这样可以进一步减少需要用的 bit 数,获得 100 分。
其他算法
比如你可以传每个值对应着哪些键,可以获得 30 分。
比如,你可以不是每次均匀分 2 组,而是直接按照哈希函数分,划分到
另外,如果是传
而且我们可以达到
然而本题中值域和定义域大小不一样,以上两个插值算法就不太妙了……但是我相信还是有只用
嗯,总之是一道做法花样繁多的通讯题!欢迎大家玩出更优的做法!