AHOI & HNOI 2018 游记

记录了作者参加AHOI竞赛的经历,包括比赛前的准备、比赛过程中的挑战及应对策略,以及比赛后的反思等内容。

紧张刺激的胡策+省选就从这一天开始了

Day 0

出发去合肥,感觉这条路走过很多次了,快到合肥的时候下雨了。
吐槽:为啥没跟大巴车走大巴车就快如闪电连服务区都不进????

今年的键盘比 noip 更差了,ahoi 主办方提供了 3 种优秀的键盘可供选择:
1. 正常键盘,仅限高水平选手 Marco_L_T 拥有。
2. 大 Enter 键盘 A,键盘敲不动,被 Enter 挤掉的 OR 和 反斜杠挤掉 Backspace 的一半,默认产品。
3. 大 Enter 键盘 B,键盘可以敲,但被 Enter 挤掉的那个格子挤掉了 Shift 的一半
于是大家纷纷要求换键盘,因为 Shift 有两个,反斜杠和 OR 不值钱,而 Backspace 打的多还打着爽,所以基本上都是 2 -> 3。

试机竟然编译完交上去就过了 FFT 模板,作为 dirt 爆炸选手实在是有点难以相信。

晚上 ygp 继续惯例开会:
“大家都有机会,zzt 和前面的差距也不是很大,因为 noip 只占 30%30%,而省选占 70%70%,所以差距也只有 … 7070 分,不是很多。”
我:***

Day 1

早上的精神状态好像还可以,希望考完之后出来还是如此,因为还要赶胡策。

8 点时进考场的检查仍然没有检查完,大概过了 5 分钟才进场,可是规定要 10 分钟才有补时,感觉有点凉。不过主办方钦定使用 .7z 格式压缩包,并断网使用 noi linux 系统。抱歉不支持 7zip,打扰了,于是 + 25 min 修锅,然后拿 U 盘一个一个拷题面,反而送给了我 20 min 打模板时间。

拿到题目的第一反应是这是本省组的题,不像和 HNOI 联考,因为题面不是 latex 而是 word,格式也非常奇怪。

正向读了一遍题,T3 可能听过部分题解,T2 可能推推可做,于是先想 T1 。想了几分钟觉得是个休闲树形 DP 题,然后写完拍了拍,拍过了就感觉挺稳的了,毕竟小数据也挺强的。

然后去看 T2 和 T3,想了大概 20 min T2,感觉一个直观的想法就是三倍长之后,把单调栈搞出来就可做了。瞎编了一下,带修的单调栈是可以可持久化平衡树维护的,那这应该是个码题,先不管。

看看 T3,80 分暴力非常蠢,后面其他的部分好像是个缩连通块。想了一会没想出怎么缩,然后意识到可以树链剖分动态 DP,对于一个点另建一个线段树维护所有轻儿子信息,常数巨大,还又是一个码码码。于是先随便写了个 O(2mn+1n)O(2m−n+1n) 的暴力跑路去看 T2 了。

可持久化平衡树这种东西是真的不想写,说不定还会被卡空间。想了想分块维护还是很靠谱的,因为范围是 105105 就开写了。先写了个暴力验了下结论,然后开始冷静分块。分块还是很好写的,卡了卡常,然后调调块大小,随机数据挺快了就溜了,反正根号半个log看起来也还行吧。。

回去写 T3 的链剖动态 DP,越写越难受,一个小时过去没啥写完的样子就扔了,于是又写 T3 的 gen,发现数组开小了,80还要卡常。。最后改了改 DP 的顺序好像快了一点,还是没什么前途啊。。

下午还要胡策,于是提前了 2 min 交卷走人了啊。。

最后得分 100 + 100 + 75,T2 竟然没被卡,T3 是真的水平不行写不出来啊。。

Day 2

那就先咕着了。

Solution

结果后来arbiter的评测又出锅了…还是不评论省队了…
Solution好像轩咕咕都扔到知乎上了啊…那我也不写了啊…
是不是可以假装完结撒花了啊。。

AHOI2018 分组问题是一道典型的组合优化问题,通常要求在满足某些约束条件的情况下将元素划分到不同的组中以达到特定目标。使用小根堆(最小堆)来解决此类问题的关键在于利用其高效的插入和提取最小值操作,从而快速找到当前状态下的最优选择。 ### 问题建模与小根堆的应用 假设问题是将一组对象分配到多个组中,每个组有一定的容量限制,并且希望最小化某种代价函数(例如总成本或最大组的大小)。可以采用以下策略: - **初始化阶段**:根据题目要求对对象进行预处理,例如按照权重、优先级或其他属性排序。 - **动态调整阶段**:使用小根堆维护当前可用的组,其中堆中的元素表示组的状态(如剩余容量、当前组的代价等)。每次从堆中取出一个最合适的组来放置下一个对象,并更新该组的状态后重新插入堆中[^1]。 这种方法特别适用于需要动态决策的问题,因为小根堆能够在 $O(\log n)$ 时间内完成插入和删除操作,保证了整体算法的时间效率。 ### 示例代码 以下是一个简化版的小根堆解决方案示例,用于模拟如何将对象分配到不同的组中,以最小化某一特定代价(例如最大组的大小): ```python import heapq def group_objects(objects, num_groups): # 初始化 num_groups 个组,每个组的初始容量为 0 heap = [(0, i) for i in range(num_groups)] # 堆中存储 (当前容量, 组编号) heapq.heapify(heap) group_sizes = [0] * num_groups # 记录每个组的实际大小 for weight in objects: # 取出当前容量最小的组 size, group_id = heapq.heappop(heap) # 将对象放入该组 new_size = size + weight group_sizes[group_id] = new_size # 更新堆 heapq.heappush(heap, (new_size, group_id)) # 返回最终各组的最大容量 return max(group_sizes) # 示例输入 objects = [5, 3, 7, 2, 6, 4] num_groups = 3 result = group_objects(objects, num_groups) print(f"最终最大组的大小为: {result}") ``` 上述代码中,`heapq` 是 Python 中实现堆结构的标准库。通过不断从堆中取出最小的组并更新其状态,能够有效地实现贪心策略,从而得到较优的分组结果。 ### 复杂度分析 - **时间复杂度**:假设对象数量为 $n$,组的数量为 $k$,则每次堆操作的时间复杂度为 $O(\log k)$,总时间为 $O(n \log k)$。 - **空间复杂度**:主要由堆和组状态数组决定,为 $O(k)$。 ### 注意事项 - 如果问题中有额外的约束(如组之间的平衡性、对象必须连续分配等),可能需要结合其他数据结构(如并查集、线段树)或更复杂的贪心策略。 - 在某些情况下,可能需要多次尝试不同的初始分组方式,以避免陷入局部最优解。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值