P9754 [CSP-S 2023] 结构体

题面

说几个坑点,一定要看提示,要不然题目感觉不是很能理解出题人的意思。
看了提示要注意到时 \(a_i\) 的倍数,而不是所有 \(a\) 的最大值。
并要注意到他按顺序排列也是要遵守对齐规则的。

思路

思路很简单,就是把所有结构体存下来,然后按照他给的公式算大小和对齐值。
然后再加入的时候先把他放进去,等后面再来一个元素时,根据公式算出这个元素的起始位置,然后减去上一个地址,得到上一个元素的大小。
在查询元素的起始位置时,就暴力的每次进去一维算一下前缀和即可。
在查询位置的元素时,就是算前缀和和当前位置比大小就好了。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
vector<vector<string>> g, gx; // 名字 类型名
vector<vector<ll>> len;       // 长度
map<string, ll> mp, dyc, lenn;
ll inn;
string nm[105];
string lxnm[105];
ll dx[105];
int ntt;
ll nadd, lstlen;
signed main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    int _;
    cin >> _;
    dyc["byte"] = 1;
    dyc["short"] = 2;
    dyc["int"] = 4;
    dyc["long"] = 8;
    lenn["byte"] = 1;
    lenn["short"] = 2;
    lenn["int"] = 4;
    lenn["long"] = 8;
    while (_--)
    {
        int op;
        cin >> op;
        // cout << op << " ";
        if (op == 1)
        {
            string lxm;
            cin >> lxm;
            ll k;
            cin >> k;
            mp[lxm] = ntt++;
            vector<string> mz, lx;
            vector<ll> lz;
            ll mx = 0, tlen = 0;
            ll tot = 0, lst = 0;
            for (int i = 1; i <= k; i++)
            {
                string lm, s;
                cin >> lm >> s;
                if (i > 1)
                {
                    tot = (tot + lst + dyc[lm] - 1) / dyc[lm] * dyc[lm];
                }
                mz.push_back(s);
                lz.push_back(lenn[lm]);
                lx.push_back(lm);
                tlen += lenn[lm];
                mx = max(mx, dyc[lm]);
                lst = lenn[lm];
            }
            g.push_back(mz);
            gx.push_back(lx);
            len.push_back(lz);
            dyc[lxm] = mx;
            lenn[lxm] = (tot + lst + mx - 1) / mx * mx;
            cout << lenn[lxm] << " " << mx << "\n";
        }
        else if (op == 2)
        {
            cin >> lxnm[inn];
            cin >> nm[inn];
            ll le = lenn[lxnm[inn]];
            ll lstadd = nadd;
            nadd -= lstlen;
            if (inn)
            {
                nadd = (nadd + lstlen + dyc[lxnm[inn]] - 1) / dyc[lxnm[inn]] * dyc[lxnm[inn]];
                dx[inn] = le;
                dx[inn - 1] += nadd - lstadd;
            }
            else
            {
                dx[inn] = le;
            }
            cout << nadd << "\n";
            nadd += le;
            lstlen = le;
            inn++;
        }
        else if (op == 3)
        {
            string s;
            cin >> s;
            int i = 0;
            string nw = "";
            while (i < s.size() && s[i] != '.')
            {
                nw += s[i];
                i++;
            }
            i++;
            string lxm;
            ll ans = 0;
            for (int j = 0; j < inn; j++)
            {
                if (nm[j] == nw)
                {
                    lxm = lxnm[j];
                    break;
                }
                ans += dx[j];
            }
            for (; i < s.size(); i++)
            {
                ll nmx = dyc[lxm];
                ll nid = mp[lxm];
                string nw = "";
                while (i < s.size() && s[i] != '.')
                {
                    nw += s[i];
                    i++;
                }
                ll tot = 0, lst = 0;
                for (int j = 0; j < g[nid].size(); j++)
                {
                    if (j)
                    {
                        tot = (tot + lst + dyc[gx[nid][j]] - 1) / dyc[gx[nid][j]] * dyc[gx[nid][j]];
                    }
                    if (g[nid][j] == nw)
                    {
                        ans += tot;
                        lxm = gx[nid][j];
                        break;
                    }
                    lst = lenn[gx[nid][j]];
                }
                // cout << nw << " " << ans << "\n";
            }
            cout << ans << "\n";
        }
        else
        {
            ll x;
            cin >> x;
            if (x >= nadd)
            {
                cout << "ERR\n";
                continue;
            }
            string ans = "";
            string lxm;
            for (int j = 0; j < inn; j++)
            {
                // cout << dx[j] << "\n";
                if (x < dx[j])
                {
                    lxm = lxnm[j];
                    ans += nm[j];
                    break;
                }
                x -= dx[j];
            }
            while (1)
            {
                if (lxm == "byte" || lxm == "int" || lxm == "short" || lxm == "long")
                {
                    if (x >= dyc[lxm])
                    {
                        ans = "ERR";
                    }
                    break;
                }
                // cout << x << "\n";
                ll nmx = dyc[lxm];
                ll nid = mp[lxm];
                bool flg = 0;
                ll tot = 0, lst = 0, lsttot = 0;
                for (int j = 0; j < g[nid].size(); j++)
                {
                    if (j)
                    {
                        tot = (tot + lst + dyc[gx[nid][j]] - 1) / dyc[gx[nid][j]] * dyc[gx[nid][j]];
                    }
                    // cout << "*" << tot << "\n";
                    if (x < tot)
                    {
                        lxm = gx[nid][j - 1];
                        ans += ".";
                        ans += g[nid][j - 1];
                        flg = 1;
                        x -= lsttot;
                        break;
                    }
                    lst = lenn[gx[nid][j]];
                    lsttot = tot;
                }
                if (!flg)
                {
                    tot = (tot + lst + dyc[lxm] - 1) / dyc[lxm] * dyc[lxm];
                    // cout << "*" << tot << "\n";
                    if (x <= tot)
                    {
                        lxm = gx[nid][g[nid].size() - 1];
                        ans += ".";
                        ans += g[nid][g[nid].size() - 1];
                        flg = 1;
                        x -= lsttot;
                    }
                }
                // cout << "*" << ans << "\n";
                if (!flg)
                {
                    ans = "ERR";
                    break;
                }
            }
            cout << ans << "\n";
        }
    }
    return 0;
}

总结

先好好读题(读完,说不定出题人写了提示呢)。
注意每道题的边界情况,别把代码写出来后再去想边界。

posted @ 2025-10-31 12:32  点燃genshin  阅读(1)  评论(0)    收藏  举报