2025牛客寒假算法基础集训营6
2025牛客寒假算法基础集训营6
A-复制鸡_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
将连续的元素看成一个即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n; cin >> n; vector<int> a; for (int i = 1; i <= n; i ++) { int x; cin >> x; if (a.empty() || x != a.back()) { a.emplace_back(x); } } cout << a.size() << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
B-好伙计猜拳_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
题目要求通过删除或交换记录使得比赛序列合法且代价最小。采用动态规划,设 \(\text{dp}[i][0/1/2]\) 表示处理到第 \(i\) 条记录时的三种状态:
- \(0\):保留当前记录不交换,且满足 \(a_i \geq a_j\);
- \(1\):删除当前记录;
- \(2\):交换当前记录的两人得分,且满足交换后 \(b_i \geq a_j\)。
初始化 \(\text{dp}[0][0] = 0\),\(\text{dp}[0][1] = c_1\),\(\text{dp}[0][2] = c_2\)。对于每条记录 \(i\),遍历前面所有可能的 \(j\),转移方程为:
最终答案为 \(\min(\text{dp}[n-1][0], \text{dp}[n-1][1], \text{dp}[n-1][2])\),时间复杂度 \(O(n^2)\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n; i64 c[3] {}; cin >> n >> c[1] >> c[2]; vector<array<int, 2>> a(n); for (auto &[x, y] : a) { cin >> x >> y; } constexpr i64 inf = 1E16; vector dp(n, array<i64, 3> {inf, inf, inf}); dp[0][0] = 0, dp[0][1] = c[1], dp[0][2] = c[2]; for (int i = 1; i < n; i ++) { dp[i][0] = c[1] * i; for (int j = 0; j < i; j ++) { if (a[i][0] >= a[j][0] && a[i][1] >= a[j][1]) { dp[i][0] = min(dp[i][0], dp[j][0] + c[1] * (i - 1 - j)); } if (a[i][0] >= a[j][1] && a[i][1] >= a[j][0]) { dp[i][0] = min(dp[i][0], dp[j][2] + c[1] * (i - 1 - j)); } } dp[i][1] = c[1] * (i + 1); for (int j = 0; j < i; j ++) { dp[i][1] = min(dp[i][1], min({dp[j][0], dp[j][1], dp[j][2]}) + c[1] * (i - j)); } dp[i][2] = c[1] * i + c[2]; for (int j = 0; j < i; j ++) { if (a[i][1] >= a[j][0] && a[i][0] >= a[j][1]) { dp[i][2] = min(dp[i][2], dp[j][0] + c[1] * (i - 1 - j) + c[2]); } if (a[i][1] >= a[j][1] && a[i][0] >= a[j][0]) { dp[i][2] = min(dp[i][2], dp[j][2] + c[1] * (i - 1 - j) + c[2]); } } } cout << min({dp[n - 1][0], dp[n - 1][1], dp[n - 1][2]}) << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
C-数列之和_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
打表,在OEIS上找到的规律。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { i64 k; cin >> k; auto lg2 = [](i64 x)->i64{ return __lg(x)/__lg(2); }; cout << 2 * (k + lg2(k + lg2(k))) << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
F-薪得体会_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
题目要求通过调整面试顺序,使得小鸡能获得的最高年薪最大化。解法核心如下:
首先将所有公司按 \(a_i\) 升序排序。设 \(\text{dp}[i]\) 表示前 \(i\) 家公司中小鸡能获得的最高年薪。对于第 \(i\) 家公司,若前 \(i-1\) 家公司中已有年薪大于等于 \(a_i\) 的 offer,则当前 offer 可提升为 \(a_i + b_i\)。转移方程为:
最终答案为 \(\text{dp}[n]\),时间复杂度为 \(O(n \log n)\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n; cin >> n; vector<pair<int, int>> p(n); for (auto &[a, b] : p) { cin >> a >> b; } ranges::sort(p); vector<int> dp(n); for (int i = 0; i < n; i += 1) { if (i) { dp[i] = max(dp[i - 1], p[i - 1].first + p[i - 1].second); } dp[i] = max(dp[i], p[i].first); if (i and dp[i - 1] >= p[i].first) { dp[i] = max(dp[i], p[i].first + p[i].second); } } cout << dp[n - 1] << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
H-小鸡的排列构造_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
若区间长度奇偶性为偶数(即 \(r_i - l_i\) 为奇数),则输出倒序排列 \([n, n-1, \ldots, 1]\)。此时任意子区间排序后,原中间位置的元素必改变,满足条件。
若区间长度奇偶性为奇数(即 \(r_i - l_i\) 为偶数),构造分块排列,形如 \([n-1, n, n-3, n-2, \ldots, 1, 2]\)。此时每个子区间排序后,原位置 \(c_i\) 的元素必不处于排序后的原位。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n, m; cin >> n >> m; vector<int> l(m), r(m), c(m); for (int i = 0; i < m; i += 1) { cin >> l[i] >> r[i] >> c[i]; } if ((r[0] - l[0]) % 2) { for (int i = n; i >= 1; i -= 1){ cout << i << " "; } } else { for (int i = 1; i <= n; i += 2) { if (i < n) { cout << n - i << " " << n - i + 1 << " "; } else { cout << "1 "; } } } cout << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
I-小鸡的排列构造的checker_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
转化为求区间内小于 \(x\) 的个数有多少个即可。
利用树状数组维护前缀和,统计每个位置 \(i\) 之前小于等于 \(p[c_i]\) 的元素个数。对于每个询问 \([l_i, r_i, c_i]\),通过差分计算排序后 \(c_i\) 的位置:首先记录 \([1, l_i-1]\) 中小于等于 \(p[c_i]\) 的元素个数 \(A\),再记录 \([1, r_i]\) 中小于等于 \(p[c_i]\) 的元素个数 \(B\),则排序后 \(c_i\) 的位置为 \(l_i - 1 + (B - A)\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; template<typename T> struct BIT { int n; vector<T> w; BIT() {} BIT(int n) { this->n = n; w.resize(n + 1); } void update(int x, T k) { for (; x <= n; x += x & -x) { w[x] += k; } } T ask(int x) { T ans = 0; for (; x; x -= x & -x) { ans += w[x]; } return ans; } }; void solve() { int n, m; cin >> n >> m; vector<int> p(n + 1); for (int i = 1; i <= n; i ++) { cin >> p[i]; } vector<int> ans(m + 1); vector g(n + 1, vector<array<int, 3>>()); for (int i = 1; i <= m; i ++) { int l, r, c; cin >> l >> r >> c; g[l - 1].push_back({ -1, p[c], i}); g[r].push_back({1, p[c], i}); ans[i] += l - 1; } BIT<int> bit(n + 1); for (int i = 1; i <= n; i ++) { bit.update(p[i], 1); for (auto &[k, x, id] : g[i]) { ans[id] += k * bit.ask(x); } } for (int i = 1; i <= m; i ++) { cout << ans[i] << "\n"; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
J-铁刀磨成针_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
设选择 \(k\) 次磨刀(\(0 \leq k \leq \min(y, n)\)),每次磨刀后攻击,攻击力依次为 \(x+1, x+2, \ldots, x+k\),总伤害为等差数列和 \(\frac{k(2x +k +1)}{2}\)。剩余 \(n -k\) 回合攻击次数为 \(m = \min(n -k, x +k)\),伤害为 \(\frac{m(2(x +k) -m +1)}{2}\)。遍历所有 \(k\),取总伤害的最大值即可。时间复杂度为 \(O(\min(y, n))\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { i64 n, x, y; cin >> n >> x >> y; i64 ans = 0; i64 m = min(y, n); for (int i = 0; i <= m; i ++) { i64 res = 0; res += (x + 1) * min(y, n); if (y < n) { res += x * (x + 1) / 2; i64 d = min(n - y, x); res -= (x - d) * (x - d + 1) / 2; } n--; y--, x++; ans = max(res, ans);; } cout << ans << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
K-鸡翻题_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
由于书的页码是连续的,且翻页操作会改变当前页码,我们需要分析页码的奇偶性。设当前页码为 \(x\) 和 \(x+1\),翻页后的页码为 \(a\) 和 \(a+1\),则 \(a + (a+1) = y\),即 \(2a + 1 = y\)。因此,\(y\) 必须为奇数,且满足 \(a = \frac{y-1}{2}\)。此外,翻页后的页码 \(a\) 必须与当前页码 \(x\) 的奇偶性相同,即 \(\frac{y-1}{2} \equiv x \pmod{2}\)。
综上,若 \(y\) 为偶数\((0\text{除外})\),或 \(\frac{y-1}{2}\) 的奇偶性与 \(x\) 不同,则输出“NO”;否则输出“YES”。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int x, y; cin >> x >> y; if ((y % 2 == 0 || ((y - 1) / 2) % 2 != x % 2) && y) { cout << "NO\n"; } else { cout << "YES\n"; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
L-变鸡器_2025牛客寒假算法基础集训营6 (nowcoder.com)
思路
先判断能否匹配字符串,然后再判断其余多出来的字符的最大个数有没有超过一半,如果超过了,则说明最后一定会有相同字符留下,而题目要求的是不同字符,所以不可行。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n; cin >> n; string s; cin >> s; string t = "CHICKEN"; int idx = 0; vector<int> cnt(26); for (auto c : s) { if (idx < t.size() && c == t[idx]) { idx ++; } else { cnt[c - 'A']++; } } if (idx == 7) { int Max = *max_element(cnt.begin(), cnt.end()); if ((n - 7) % 2 == 0 && Max <= (n - 7) / 2) { cout << "YES\n"; return; } } cout << "NO\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18718738
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步