【难题总结】P9754 [CSP-S 2023] 结构体

题目:P9754 [CSP-S 2023] 结构体

调试时长:\(10\) 小时

题目做法:大模拟

对齐要求

非常重要,一定不能理解错!

每一个元素(无论是结构体中的或者是全局的)都要按照自己的对齐要求对齐。

比如类型为 \(struct\ a\) 的元素 \(x\) 的对齐要求是 \(8\) ,那么它的起始地址必须是 \(8\) 的倍数。

具体的处理方法是:\(pos\) 代表现在最后一个已用的地址(注意区分结构体内外),每次先把 \(pos=((pos-1)/align+1)*align\) ,然后再把 \(pos=pos+size\)

记得结构体最后要按照整个结构体的对齐要求“封装”

数据储存

定义两个结构体,一个存储type,一个存储element

  • type包含:名称,大小,成员名称、类型,对齐要求(还可以加入“成员占用空间”)

  • element包含:名称,类型,起始内存地址

有了这些数据,就可以在任何时候算出需要的数据。

另外建立 defined_type / defined_element 数组储存已定义的类型和元素,并且建立map映射<name,type><name,element>< <address_s,adderss_e>,element>

为了节省时间复杂度,用数组下标(或者指针)表示对应的type。指针更方便。

初始化

把四种基本类型加入defined_type

操作1

先读入所有的成员,算出整个结构体的对齐要求,与此同时,维护pos,表示已经用了的内存(从0开始)。最后把pos与整个结构体的要求对齐,储存为size。这个过程中可以更新memberL,memberR。

操作2

照着题意做就行了。注意全局的元素也要遵循对齐规则。

操作3

先按照.划分输入,存进队列里。

紧接着,用map查找队头对应的元素。然后沿着队列一步步遍历成员并深入。

最后输出答案。

操作4

最难的操作,困扰了我好几个小时

难点在于要特判由于对齐导致的空洞。

首先在地址到元素的映射中找到addr所在的元素(注意特判map边界),然后像操作3一样遍历知道找到答案或者进入空洞。这里就可以用上预处理的memberL和memberR。

总结

正常蓝色难度的大模拟。看来大模拟还是得练。暂定下一次练习题单中再重新写一遍。

posted @ 2025-02-20 20:55  Luke_li  阅读(34)  评论(0)    收藏  举报