写在前面,本文是博主打春赛的记录,另外,博主是“菜鸡”
比赛来晚了,打开电脑,进入竞赛界面,ohhhhhhhhhhhh,有点高端,还有动态榜,有点ICPC和ACM的味道了,总体浏览题目,2 + 1 + 2 五个题,简单+中等+困难。直接抛弃后两个困难题。
第一题:宝石补给,题意就是给一个数组表示每人所拥有的宝石,然后一个操作数组,把第一个操作数的宝石的一半(下取整)给第二个操作数,最终返回一个最大宝石数与最小宝石数的差。纯模拟,数据量不大,Easy题。直接贴代码!
class Solution {
public:
int giveGem(vector<int>& gem, vector<vector<int>>& operations) {
for(auto a : operations)
{
int t = gem[a[0]] / 2;
gem[a[0]] -= t;
gem[a[1]] += t;
}
sort(gem.begin(), gem.end());
int n = gem.size();
return gem[n - 1] - gem[0];
}
};
第二个Easy题,估计坑害不少人,第一想法是递归回溯,觉得dp也能写,但是我dp很菜,就在设计dfs,样例没过,再读题。每种食材只能做一个。加上限制条件。样例没过,忘了写回溯。又看了看数据限制:食材规定5种不变,烹饪菜最多8种。我一拍桌子,心想二进制枚举保证双百。(关于二进制枚举可以看一下这篇文章-LeetCode射箭比赛-) 按照题意,枚举每种方案食材能做几种烹饪菜,这种方案食材是否够用,方案可行后,饱腹感是否满足limit,满足limit后,维护最大的美味感即可!
class Solution {
public:
int perfectMenu(vector<int>& m, vector<vector<int>>& cb, vector<vector<int>>& a, int limit) {
int ans = -1;
int n = cb.size();
for(int i = 0; i < 1 << n; i++)
{
vector<int> t(m);
int get = 0 , score = 0;
for(int j = 0; j < n; j++)
{
if(i & (1 << j))
{
bool f = true;
for(int k = 0; k < 5; k++)
{
if(t[k] >= cb[j][k])
t[k] -= cb[j][k];
else
f = false;
}
if(f)
{
score += a[j][0];
get += a[j][1];
}
}
}
if(get >= limit)
if(score > ans)
ans = score;
}
return ans;
}
};
第三题的 线段树,本来想用差分维护,但是109算前缀和,肯定LTE,线段树我这个“菜鸡”还没学透。就放弃了,竞赛结束后,看到有人用set维护区间范围的。大家可以去网站看一下题解。应该是练得题多了,比较有想法。也贴一个CV的代码
class Solution {
set<int> st;
void dfs(TreeNode *node) {
if (node == nullptr) return;
st.insert(node->val);
dfs(node->left);
dfs(node->right);
}
public:
int getNumber(TreeNode* root, vector<vector<int>>& ops) {
dfs(root);
int ans = 0;
for (int i = (int) ops.size() - 1; i >= 0; i--) {
while (true) {
auto it = st.lower_bound(ops[i][1]);
if (it == st.end() || (*it) > ops[i][2]) break;
st.erase(it);
if (ops[i][0]) ans++;
}
}
return ans;
}
};