1 solutions

  • 1
    @ 2025-5-19 20:04:13

    阅读理解大模拟,没什么好说的,我主要讲一下自己处理这种问题的设计思路和习惯。

    首先,从常数设计的角度考虑,STL 嵌套多了会特别慢,因此可以将角色和用户都分别设计一个 unordered_map<string, int> 类,将每一个字符串映射到静态数组的下标上,实际数据库的信息用静态数组来存储就好了。

    比如下面存储角色的时候,外层是数组,里面再用哈希 unordered_set 去存储 op(操作清单),res_cat(资源种类清单),res_name(资源名称清单)

    然后角色内部的操作权限写一个成员函数即可,遵循判断过程的 4 个条件去写就行了。

    const int N = 200010;
    // character
    int chara_cnt;
    std::unordered_map<std::string, int> chara;
    const std::string all = "*";
    struct chara_list
    {
        std::unordered_set<std::string> op_list;
        std::unordered_set<std::string> res_cat_list;
        std::unordered_set<std::string> res_name_list;
    
        void add_op(const std::string& s) { op_list.insert(s); }
        void add_res_cat(const std::string& s) { res_cat_list.insert(s); }
        void add_res_name(const std::string& s) { res_name_list.insert(s); }
    
        bool access(const std::string& op, const std::string& res_cat, const std::string& res_name)
        {
            if (!(op_list.count(all) || op_list.count(op)))
                return 0;
            if (!(res_cat_list.count(all) || res_cat_list.count(res_cat)))
                return 0;
            if (!(res_name_list.empty() || res_name_list.count(res_name)))
                return 0;
            return 1;
        }
    };
    chara_list ch_list[N];
    

    那么在题面最开始读取 nn 个角色的时候,就可以这样去处理:

        std::ios::sync_with_stdio(0);
        std::cin.tie(0), std::cout.tie(0);
    
        std::cin >> n >> m >> q;
        std::string s;
        // input character
        while (n--)
        {
            std::cin >> s; // name
            if (!chara.count(s)) // 如果是头一次出现的角色,则新建 id 表示对应下标的映射
                chara[s] = ++chara_cnt;
            int idx = chara[s];
    
            int x = 0;
            std::cin >> x;
            while (x--)
                std::cin >> s, ch_list[idx].add_op(s);
            std::cin >> x;
            while (x--)
                std::cin >> s, ch_list[idx].add_res_cat(s);
            std::cin >> x;
            while (x--)
                std::cin >> s, ch_list[idx].add_res_name(s);
        }
    

    接下来读取角色关联则可以使用类似的方式,读入了字符串之后,先映射到对应的数字。然后对于用户和用户组,同样使用 stringint 映射的 unordered_map 来维护用户以及用户组即可。

    // user
    int single_user_cnt;
    std::unordered_map<std::string, int> single_user;
    // user group
    int group_cnt;
    std::unordered_map<std::string, int> group_user;
    
    struct user_list
    {
        std::vector<int> ch_list_idx;
        void add_chara(int idx) { ch_list_idx.push_back(idx); }
    };
    

    单独用户和用户组都是记录若干个角色的,以此来表示角色关联的关系,因此在输入角色关联时,把他们加入关系组即可。

        while (m--)
        {
            std::cin >> s;
            int idx = chara[s];
    
            std::string cat, name;
            int x = 0;
            std::cin >> x;
            while (x--)
            {
                std::cin >> cat >> name;
                if (cat == "u")
                {
                    if (!single_user.count(name))
                        single_user[name] = ++single_user_cnt;
                    int u_idx = single_user[name];
                    single_list[u_idx].add_chara(idx);
                }
                else
                {
                    if (!group_user.count(name))
                        group_user[name] = ++group_cnt;
                    int u_idx = group_user[name];
                    group_list[u_idx].add_chara(idx);
                }
            }
        }
    

    而用户判断操作的话,则参照用户的判断流程,需要传入单个用户对应的 id,输入的所有用户组,以及对应到每个角色的操作。

    bool judge(int user, const std::vector<int>& group, const std::string& op, const std::string& cat, const std::string& name)
    {
        if (user)
        {
            for (size_t i = 0; i < single_list[user].ch_list_idx.size(); ++i)
            {
                int idx = single_list[user].ch_list_idx[i];
                if (ch_list[idx].access(op, cat, name))
                    return 1;
            }
        }
        for (size_t i = 0; i < group.size(); ++i)
        {
            for (size_t j = 0; j < group_list[group[i]].ch_list_idx.size(); ++j)
            {
                int idx = group_list[group[i]].ch_list_idx[j];
                if (ch_list[idx].access(op, cat, name))
                    return 1;
            }
        }
        return 0;
    }
    

    因此整体的代码如下,需要分模块慢慢进行理解。

    #include <iostream>
    #include <string>
    #include <vector>
    #include <unordered_map>
    #include <unordered_set>
    const int N = 200010;
    int n, m, q;
    // character
    int chara_cnt;
    std::unordered_map<std::string, int> chara;
    const std::string all = "*";
    struct chara_list
    {
        std::unordered_set<std::string> op_list;
        std::unordered_set<std::string> res_cat_list;
        std::unordered_set<std::string> res_name_list;
    
        void add_op(const std::string& s) { op_list.insert(s); }
        void add_res_cat(const std::string& s) { res_cat_list.insert(s); }
        void add_res_name(const std::string& s) { res_name_list.insert(s); }
    
        bool access(const std::string& op, const std::string& res_cat, const std::string& res_name)
        {
            if (!(op_list.count(all) || op_list.count(op)))
                return 0;
            if (!(res_cat_list.count(all) || res_cat_list.count(res_cat)))
                return 0;
            if (!(res_name_list.empty() || res_name_list.count(res_name)))
                return 0;
            return 1;
        }
    };
    chara_list ch_list[N];
    // user
    int single_user_cnt;
    std::unordered_map<std::string, int> single_user;
    // user group
    int group_cnt;
    std::unordered_map<std::string, int> group_user;
    
    struct user_list
    {
        std::vector<int> ch_list_idx;
        void add_chara(int idx) { ch_list_idx.push_back(idx); }
    };
    
    user_list single_list[N], group_list[N];
    
    bool judge(int user, const std::vector<int>& group, const std::string& op, const std::string& cat, const std::string& name)
    {
        if (user)
        {
            for (size_t i = 0; i < single_list[user].ch_list_idx.size(); ++i)
            {
                int idx = single_list[user].ch_list_idx[i];
                if (ch_list[idx].access(op, cat, name))
                    return 1;
            }
        }
        for (size_t i = 0; i < group.size(); ++i)
        {
            for (size_t j = 0; j < group_list[group[i]].ch_list_idx.size(); ++j)
            {
                int idx = group_list[group[i]].ch_list_idx[j];
                if (ch_list[idx].access(op, cat, name))
                    return 1;
            }
        }
        return 0;
    }
    
    int main()
    {
        std::ios::sync_with_stdio(0);
        std::cin.tie(0), std::cout.tie(0);
    
        std::cin >> n >> m >> q;
        std::string s;
        // input character
        while (n--)
        {
            std::cin >> s; // name
            if (!chara.count(s))
                chara[s] = ++chara_cnt;
            int idx = chara[s];
    
            int x = 0;
            std::cin >> x;
            while (x--)
                std::cin >> s, ch_list[idx].add_op(s);
            std::cin >> x;
            while (x--)
                std::cin >> s, ch_list[idx].add_res_cat(s);
            std::cin >> x;
            while (x--)
                std::cin >> s, ch_list[idx].add_res_name(s);
        }
    
        while (m--)
        {
            std::cin >> s;
            int idx = chara[s];
    
            std::string cat, name;
            int x = 0;
            std::cin >> x;
            while (x--)
            {
                std::cin >> cat >> name;
                if (cat == "u")
                {
                    if (!single_user.count(name))
                        single_user[name] = ++single_user_cnt;
                    int u_idx = single_user[name];
                    single_list[u_idx].add_chara(idx);
                }
                else
                {
                    if (!group_user.count(name))
                        group_user[name] = ++group_cnt;
                    int u_idx = group_user[name];
                    group_list[u_idx].add_chara(idx);
                }
            }
        }
    
        int user = 0;
        int gcnt;
        std::vector<int> group;
        std::string _op, reslist, resname;
    
        while (q--)
        {
            std::cin >> s;
            user = single_user[s];
            // std::cout << "add user " << user << '\n';
            group.clear();
            std::cin >> gcnt;
            while (gcnt--)
            {
                std::cin >> s;
                if (group_user.count(s))
                    group.push_back(group_user[s]); //, std::cout << "add group " << group_user[s] << '\n';
            }
            std::cin >> _op >> reslist >> resname;
            std::cout << judge(user, group, _op, reslist, resname) << '\n';
        }
    }
    
    • 1

    Information

    ID
    32
    Time
    5000ms
    Memory
    512MiB
    Difficulty
    3
    Tags
    # Submissions
    18
    Accepted
    3
    Uploaded By