【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
-
若堆
heap.size()<k
时,他总能击败所有比他攻击力小的那些猎人。那么cumsum = sum(B[j].money for j if j < i)
事实上不用每次对每个i维护一个堆。一共需要一个堆即可。只不过需要每次更新。(也就是维护一个动态流中的前k个?) -
若堆
heap.size()>=k
,他必须选择排序后出现在它之前的k个money最多的猎人。并且,如果对于j<i<m,若猎人i在此时,由于猎人j的money排在第k位之外。那么猎人i不选择击败猎人j,那么对于i之后出现的猎人m,也一定不会选择击败猎人j -
那么此时cumsum需要换出堆顶元素。并不断将遇到的、大于堆顶元素的猎人j的money
push
进堆。
#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;
}