P9754 [CSP-S 2023] 结构体

我是模拟大王,考场上想了两小时 T2 不会,一个小时写完这题过大样例了。

先把所有类型抽象成一个结点 node,只需要维护其大小以及对齐信息。字符串的判断使用哈希实现。

接下来一个一个操作实现:

$1$ 操作

说人话就是新建一个点然后连一些边。算对齐信息是好做的,因为底下的结点我们都知道对齐信息;算空间也是好做的,因为底下的结点我们都知道空间大小,顺次递推即可,为了维护 $3,4$ 操作我们维护一个点每个子节点的空间左端点,存储在了 umap<int, pair<int, int>> sn 中,其中前者是字符串的哈希值,pair<int, int> 表示子结点编号以及在当前结点左端点为 $0$ 时,左端点的对齐信息。然后最后要把空间对齐到自己的对齐信息上。

$2$ 操作

开一个数组 w 表示当前声明了的结点实例的 node 编号,beg 表示声明了的每个实例的左端点。暴力维护即可。

$3$ 操作

一个一个跳,每次加上当前结点的左端点编号即为全局左端点。

$4$ 操作

跟 $3$ 操作差不多,模仿平衡树思想,一个一个判断 $addr$ 是否在当前区间内,是的话就往下跳,找不到往下就输出 ERR

考场代码

#include <bits/stdc++.h>
#define int long long
#define umap unordered_map

using namespace std;

const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;

struct node {
    int siz, lim;
    node() = default;
    node(int s, int l): siz(s), lim(l) {}
};

int T;
node tr[maxn];
int tot;
umap<int, pair<int, int>> sn[maxn];
vector<int> snn[maxn];
umap<int, int> bk;

int hsh(string s) {
    int y = 0;
    for (int i = 0; i < s.length(); i++) y = (y * 251 % mod + s[i]) % mod;
    return y;
}

int w[maxn];
int cnt;
umap<int, int> ck;
int beg[maxn];
string eriri[maxn];
int now;
umap<int, string> bas;

signed main() {
    //freopen("struct.in", "r", stdin);
    //freopen("struct.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    bk[557350929] = 1;
    bk[101086854] = 2;
    bk[6642831] = 3;
    bk[714851925] = 4;
    tr[1].siz = tr[1].lim = 1;
    tr[2].siz = tr[2].lim = 2;
    tr[3].siz = tr[3].lim = 4;
    tr[4].siz = tr[4].lim = 8;
    tot = 4;
    cin >> T;
    while (T--) {
        int op;
        cin >> op;
        if (op == 1) {
            string s, t, nam;
            int k;
            cin >> s >> k;
            int u = ++tot;
            bk[hsh(s)] = u;
            int cur = 0;
            for (int i = 1; i <= k; i++) {
                cin >> t >> nam;
                int v = bk[hsh(t)];
                cur = (cur + tr[v].lim - 1) / tr[v].lim * tr[v].lim;
                sn[u][hsh(nam)] = {v, cur};
                snn[u].push_back(hsh(nam));
                bas[hsh(nam)] = nam;
//              cout << u << "->" << nam << " (" << v << " " << cur << ")" << endl;
                cur += tr[v].siz;
                tr[u].lim = max(tr[u].lim, tr[v].lim);
            }
            cur = (cur + tr[u].lim - 1) / tr[u].lim * tr[u].lim;
            tr[u].siz = cur;
            cout << tr[u].siz << " " << tr[u].lim << endl;
        } else if (op == 2) {
            string s, t;
            cin >> s >> t;
            w[++cnt] = bk[hsh(s)];
            eriri[cnt] = t;
            ck[hsh(t)] = cnt;
            now = (now + tr[w[cnt]].lim - 1) / tr[w[cnt]].lim * tr[w[cnt]].lim;
            cout << now << endl;
            beg[cnt] = now;
            now += tr[w[cnt]].siz;
        } else if (op == 3) {
            string s;
            cin >> s;
            vector<int> path;
            int sta = 0;
            for (int i = 0; i < s.length(); i++) {
                if (s[i] == '.') {
                    int ter = i - 1;
                    path.push_back(hsh(s.substr(sta, ter - sta + 1)));
//                  cout << sta << " " << ter << endl;
                    sta = i + 1;
                } 
            }
//          cout << sta << " " << s.length() - 1 << endl;
            path.push_back(hsh(s.substr(sta, s.length() - sta)));
            int u = w[ck[path[0]]], pos = beg[ck[path[0]]];
            for (int i = 1; i < path.size(); i++) {
                pos += sn[u][path[i]].second;
//              cout << u << endl;
                u = sn[u][path[i]].first;
            }
            cout << pos << endl;
        } else if (op == 4) {
            int add;
            cin >> add;
            int p = 0;
            for (int i = cnt; i; i--) {
                if (beg[i] <= add) {
                    p = i;
                    break;
                }
            }
            if (!p || beg[p] + tr[w[p]].siz - 1 < add) {
                cout << "ERR" << endl;
                continue;
            }
//          cout << p << endl;
            int u = w[p], nw = beg[p];
            string aaans = eriri[p];
            while (true) {
                if (u <= 4) {
                    cout << aaans << endl;
                    break;
                }
                bool fl = 0;
                for (int h : snn[u]) {
//                  cout << u << "-" << bas[h] << "->" << sn[u][h].first << " " << sn[u][h].second << " " << tr[sn[u][h].first].siz << " " << nw << endl;
                    if (sn[u][h].second + nw <= add && sn[u][h].second + nw + tr[sn[u][h].first].siz > add) {
                        nw += sn[u][h].second;
                        aaans += ".";
                        aaans += bas[h];
                        fl = 1;
                        u = sn[u][h].first;
                        break;
                    }
                }
                if (!fl) {
                    cout << "ERR" << endl;
                    break;
                }
            }
        }
    }
    return 0;
}
posted @   TernaKagiri  阅读(31)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示