首页 > 其他分享 >P9754 [CSP-S 2023] 结构体 题解

P9754 [CSP-S 2023] 结构体 题解

时间:2023-10-22 14:14:29浏览次数:32  
标签:std P9754 Obj 题解 align tnam offset now CSP

前言

在考场上调了 2h+ 还没调出来,并且 T4 也没来得及做。希望看到这段文字的你能避免这样的悲剧。

正文

题目要求动态创建类型,于是我用结构体代表一个 struct(禁止套娃),要新建就 new 出来一个。(最后也没 delete

struct Obj{
    typnam tnam;
    ll len, align;
    std::map<std::string, std::pair<Obj*, ll>> subs;
    Obj():tnam(), len(0), align(0){}
    Obj(std::string nam, ll le=0, ll ali=0):tnam(nam), len(le), align(ali){}
};

由于结构体的名称和变量名称容易混淆,我用 typnam 标注了结构体的名称。

using typnam = std::string;

声明了结构体之后,题目要求根据名称找出一个结构体,我用 std::set 保存。这里也可以用 std::map

struct comp_obj_by_typnam{ bool operator()(Obj *a, Obj *b) const { return a->tnam < b->tnam; } };
std::set<Obj*, comp_obj_by_typnam> decl_objs = {&BByte, &SShort, &IInt, &LLong};
Obj *get_obj_by_tname(typnam &tnam){
    Obj tmp(tnam);
    return *decl_objs.find(&tmp);
}

对于已存在的变量,我用一个 map 保存名称,类型和起始位置。

其实这里也可以新建一个特殊的 struct,就像森林转树要加一个超级根一样。这样可以避免一些重复的代码。

std::map<std::string, std::pair<Obj*, ll>> exist_objs;
ll global_offset = 0;

关于如何计算对齐:

设第 \(i\) 个被定义的元素大小为 \(s_i\),对齐要求为 \(a_i\),起始地址为 \(b_i\);
则 \(b_1=0\),对于 \(2\le i\), \(b_i\) 为满足 \(b_{i−1}+s_{i−1} \le b_i\) 且 \(a_i\) 整除 \(b_i\) 的最小值。

记 \(k=b_{i-1}+s_{i-1}\),若 \(k \equiv 0 \pmod {a_i}\),则 \(b_i\) 正好可以放入;

否则,\(b_i = k+a_i-(k \bmod {a_i})\)。

ll get_start_addr(ll old_offset, Obj const *me){
    if(old_offset % me->align) old_offset += me->align - old_offset%me->align;
    return old_offset;
}

关于访问某个元素:

读入名称 s 后,可以用 s.substr(0, s.find(".")) 找到 struct 名。

附完整代码,用于 debug:

完整代码 ```cpp #include #define UP(i,s,e) for(auto i=s; i<e; ++i)="" namespace="" m{="" }{{{="" using="" std::cin;="" std::cout;="" typnam="std::string;" ll="long" long;="" struct="" obj{="" tnam;="" len,="" align;="" std::map<std::string,="" std::pair<obj*,="">> subs; Obj():tnam(), len(0), align(0){} Obj(std::string nam, ll le=0, ll ali=0):tnam(nam), len(le), align(ali){} }; Obj BByte = {"byte", 1, 1}, SShort = {"short", 2, 2}, IInt = {"int", 4, 4}, LLong = {"long", 8, 8}; int in; struct comp_obj_by_typnam{ bool operator()(Obj *a, Obj *b) const { return a->tnam < b->tnam; } }; std::map<std::string, std::pair<obj*,="" ll="">> exist_objs; ll global_offset = 0; std::set<obj*, comp_obj_by_typnam=""> decl_objs = {&BByte, &SShort, &IInt, &LLong}; Obj *get_obj_by_tname(typnam &tnam){ Obj tmp(tnam); return *decl_objs.find(&tmp); } ll get_start_addr(ll old_offset, Obj const *me){ if(old_offset % me->align) old_offset += me->align - old_offset%me->align; return old_offset; } void declare_struct(){ std::string is; int ik; cin >> is >> ik; Obj *now = new Obj; now->tnam = is; ll nowoff = 0; UP(i, 0, ik){ std::string it, in; cin >> it >> in; Obj *me = get_obj_by_tname(it); now->align = std::max(now->align, me->align); nowoff = get_start_addr(nowoff, me); now->subs.insert({in, {me, nowoff}}); nowoff += me->len; } now->len = get_start_addr(nowoff, now); decl_objs.insert(now); cout << now->len << ' ' << now->align << '\n'; } void create_obj(){ std::string it, in; cin >> it >> in; Obj *now = get_obj_by_tname(it); global_offset = get_start_addr(global_offset, now); exist_objs.insert({in, {now, global_offset}}); cout << global_offset << '\n'; global_offset += now->len; } void access_obj_recursive(ll sum_offset, std::string &is, Obj *now){ auto pl = is.find('.'); if(pl == std::string::npos){ cout << sum_offset+now->subs[is].second << '\n'; return; } auto &now_info = now->subs[is.substr(0, pl)]; now = now_info.first; is.erase(0, pl+1); access_obj_recursive(sum_offset + now_info.second, is, now); } void access_obj(){ std::string is; cin >> is; auto pl = is.find('.'); if(pl == std::string::npos){ cout << exist_objs[is].second << '\n'; return; } auto &now_info = exist_objs[is.substr(0, pl)]; Obj *now = now_info.first; is.erase(0, pl+1); access_obj_recursive(now_info.second, is, now); } void access_addr_recursive(ll addr, Obj *now, std::string &ans){ if(now == &BByte || now == &SShort || now == &IInt || now == &LLong){ cout << ans << '\n'; return; } for(auto &i:now->subs){ if(i.second.second <= addr && i.second.second + i.second.first->len > addr){ ans += '.'; ans += i.first; access_addr_recursive( addr-i.second.second, i.second.first, ans); return; } } cout << "ERR\n"; } void access_addr(){ ll addr; cin >> addr; std::string ans; for(auto &i:exist_objs){ if(i.second.second <= addr && i.second.second + i.second.first->len > addr){ ans = i.first; access_addr_recursive( addr-i.second.second, i.second.first, ans); return; } } cout << "ERR\n"; } void work(){ cin >> in; UP(i, 0, in){ int op; cin >> op; if(op == 1){ declare_struct(); } else if(op == 2){ create_obj(); } else if(op == 3){ access_obj(); } else { access_addr(); } } } } // {}}} int main(){m::work(); return 0; } ```

标签:std,P9754,Obj,题解,align,tnam,offset,now,CSP
From: https://www.cnblogs.com/x383494/p/17780380.html

相关文章

  • 游记——CSP-S2023 SD 第二轮游记
    游记——CSP-S2023SD第二轮游记Day0晚上从青岛出发,到了日照,路挺顺。试机,门口很堵,还好我进的早。考场是C404,转了几圈才找到(和几年前的小学组很近大学操场有小情侣,羡慕,呜呜呜。。。考场FTP没调好,说19:30考试19:45都没进屋。一堆普及组的来提高组试机(旁边的大佬1......
  • 2023CSP-S游记
    2023CSP-S游记赛前上午去花卉市场看了半天花,算是放松放松,主要是为了晚上给干妈过50岁生日。还以为是2点开始,1点40多就到了,然后去买了杯奶茶,然后进场。结果我是第一考室第一个QwQ赛时花了半个小时看题,思路都是很快的出来了。T1以为是一个分讨,结果直接枚举就可以了,......
  • CSP-S 2023 游记
    CSP-S2023游记Day1上午早上起来洗完漱,逛了一会淘宝便打开电脑,看了看谷群,结果J组的题已经出来了???这变成同步赛了吗?但群里没有人发(看来大家都遵纪守法),我顺着源头找到洛谷团队并成功收到了题和密码,看样子应该是有考场没关网(听说那个考场有人玩原神???)随即简单看了一下J组的题目......
  • CSP-J2023游记
    第一轮Day00天警告Day1开考,听说是姜sir批卷,也没啥好紧张的了。选择题靠我垃圾的C++,第一题就错了/cf,两道数学题和位运算倒是秒切。阅读程序很顺利,只错了一道,到了补全程序只剩\(10\text{min}\)了,瞎蒙了几个,居然对的还不少。出来后找byr对答案,他说他忘了,差评。Day\(\in......
  • 2023 CSP-J/S 复赛(简要思路)
    省流:都没AK,但是思路都没假。(没更新,小声)Japple\(O(\logn)\)模拟,因为\(n\)每次乘\(\frac{2}{3}\)。\(x≡1\mod3\)时第\(x\)个苹果会被拿走。road贪心。每次选价格最少的油加。uqe按照题意模拟。\(c=0\)也许要特判。bus我的方法是二分答案然后倒着最短路,\(mn_{i,......
  • CSP2023 游记
    前言停了大概二十几天的课,考出了这样一个难看的成绩。虽然用教练的话来说,只是CSP,还是要看noip。希望noip好运吧。初赛今年初赛成绩在高中部好像还不错?但是被初中学弟吊打了。https://www.luogu.com.cn/discuss/687363Day-1颓。一整天只看题不写题。上午和同学讨......
  • CSP-S 2023 题解
    expect:\(100+100+65+25=290\)真实:\(100+85+0+15=205\),rk62感觉自己考的好烂好烂好烂T4这么简单竟然想不出来,感觉如果自己不被T4吓到,全做出来其实有望365+?今年CSP-S怎么这么简单吓得我不敢做了T1暴力T2考场做法:设\(lst_i\)表示\(a_i=a_{lst_i}\)并且\((......
  • pip安装慢问题解决
     一、永久修改pip软件安装默认源使用pipconfigsetglobal.index-url来直接指定下载源的URL,这样就不用手动修改配置文件了pipconfigsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simple以下是国内互联网常用的pypi安装源URL,在国内互联网下载的速度非常快......
  • CSP2023 补题游记
    day-?10月14日,和zybzxh打洛谷普及组模拟赛,我们三个没一个ak(xs)我和zyb挂T3,zxh不会T4。大概就这样打了356.10月15日切CF的dp题。爽洛谷的膜你赛没打16日至19日继续磕CFdp题。有点上难度哈。21日,比赛日上午继续怼恶心的CFdp。中午12......
  • CSP2023游记
    10.22.9:40不知不觉也轮到我写游记了。DAY-1这天打了一场模拟赛,T1想半天,总觉得是道DP,然后并不是。......