【2021】牛客模考(二模)编程题集合 3题

这篇博客介绍了两个编程题目,第一题涉及根据攻击和金钱值对Hunter对象排序,并使用堆来解决限制条件下的问题。第二题通过实现字典树(Trie)解决字符串查询效率问题,避免超时。这两道题目都展示了数据结构和算法在实际问题中的应用。
摘要由CSDN通过智能技术生成

【2021】牛客模考(二模)编程题集合 3题

第二题

先读入attack,money,重构一个对象Hunter。(存储了在原序列的index)将每个Hunter按attack排序。
再对排序好的序列,进行答案更新。由于猎人i只能击败attack[j] < attack[i](for 0<= j <i )的。那么如果还有k的限制。那一定是得从比他攻击力小的那些猎人中选money降序排列的前k个。那么这应该使用堆。

  • 对于排序后序列B,若有i=0,他无法击败任何人。
    ans[B[i].index] = money[B[i].index]即为他原本所持有的。
  • 对于i>0
  1. 若堆heap.size()<k时,他总能击败所有比他攻击力小的那些猎人。那么cumsum = sum(B[j].money for j if j < i)
    事实上不用每次对每个i维护一个堆。一共需要一个堆即可。只不过需要每次更新。(也就是维护一个动态流中的前k个?)

  2. 若堆heap.size()>=k,他必须选择排序后出现在它之前的k个money最多的猎人。并且,如果对于j<i<m,若猎人i在此时,由于猎人j的money排在第k位之外。那么猎人i不选择击败猎人j,那么对于i之后出现的猎人m,也一定不会选择击败猎人j

  3. 那么此时cumsum需要换出堆顶元素。并不断将遇到的、大于堆顶元素的猎人j的moneypush进堆。

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

class Hunter {
public:
    int attack;
    int money;
    int index;
    Hunter(int attack,int money,int index) {
        this->attack = attack;
        this->index = index;
        this->money = money;
    };
};
class Solution{
public:
    Solution(){};
    vector<int> solve(const vector<int> & attack,const vector<int>& money,int k) {
        vector<Hunter> B;
        int n = attack.size();
        for(int i =0;i<n;++i) {
            B.emplace_back(attack[i],money[i],i);
        }
        sort(B.begin(),B.end(),[&](Hunter v1,Hunter v2){
            return v1.attack < v2.attack;
        });
        vector<int> ans(n);
        priority_queue<int,vector<int>,greater<int>> heap;
        int cur_sum = 0;
        //按排序遍历
        for(int i =0;i<n;++i) {
            int index = B[i].index;
            ans[index] = money[index];
            //维护一个堆。
            //i =0则没有比他attack小的了
            if(i !=0) {
                //避免了重复cumsum
                int prev = i - 1;
                //不够k个,直接push
                if(heap.size() < k) {
                    cur_sum += B[prev].money;
                    heap.push(B[prev].money);

                } else if(B[prev].money > heap.top()) {
                    //已经满了k个,并且前一个比堆顶元素money大,及时用它换出堆顶元素。
                    cur_sum = cur_sum - heap.top() + B[prev].money;
                    heap.pop();
                    heap.push(B[prev].money);
                }
                ans[index] += cur_sum;
            }
        }
        return ans;
    }
};
int main() {
    int n,k;
    cin>>n>>k;
    vector<int> attack(n);
    vector<int> money(n);
    int i=0;
    int N = n;
    while(N--) {
        cin >> attack[i];
        ++i;
    }
    N =n;
    i = 0;
    while(N--) {
        cin >> money[i];
        ++i;
    }
    auto s = Solution();
    auto arr = s.solve(attack,money,k);
    for(int i =0;i<arr.size();++i){
        cout<<arr[i];
        if(i < arr.size()-1) {
            cout<<" ";
        }
    }
    return 0;
}

第三题

尝试vector<string>存储超时了。使用了字典树。500ms

#include<iostream>
#include<vector>
using namespace std;

struct TireNode{
    int cnt;
    vector<TireNode*> children;
    TireNode():cnt(0),children(10, nullptr){};
};
class IDTree{
    TireNode * root;

public:
    IDTree(){
        this->root = new TireNode();
    };
    void insert(const string & id){
        auto p = root;
        //维护LCS长度为0的公共数量,n
        for(auto &c:id){
            //cout<<c;
            ++p->cnt;
            if(p->children[c-'0'] == nullptr) {
                p->children[c-'0'] = new TireNode();
            }
            p = p->children[c-'0'];
        }
        //cout<<endl;
    };
    string query(string query_id) {
        auto p = root;
        int length=0;
        int cnt = root->cnt;
        for(int i=0;i<18;++i){
            char c = query_id[i];
            if(query_id[i] == c && p->children[c-'0']){
                cnt = p ->children[c-'0']->cnt;

                p = p->children[c-'0'];
                ++length;

            } else {
                break;
            }
        }
        return to_string(length) + " " + to_string(cnt);
    }
};

int main() {
    int n,Q;
    cin >>n>>Q;
    auto tree = new IDTree();
    string id;
    while(n--) {
        cin>>id;
        tree->insert(id);
    }
    //query
    string query_id;
    //cout << "query:"<<endl;
    while(Q--) {
        cin >> query_id;
        cout<<tree->query(query_id)<<endl;
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值