回头看,轻舟已过万重山.|

Ke_scholar

园龄:2年1个月粉丝:30关注:10

2025-02-16 20:47阅读: 15评论: 0推荐: 0

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\),转移方程为:

\[\text{dp}[i][0] = \min \begin{cases} c_1 \cdot i, \\ \text{dp}[j][0] + c_1 \cdot (i - 1 - j) \quad \text{if} \quad a_i \geq a_j \land b_i \geq b_j, \\ \text{dp}[j][2] + c_1 \cdot (i - 1 - j) \quad \text{if} \quad a_i \geq b_j \land b_i \geq a_j. \end{cases} \]

\[\text{dp}[i][1] = \min \begin{cases} c_1 \cdot (i + 1), \\ \min(\text{dp}[j][0], \text{dp}[j][1], \text{dp}[j][2]) + c_1 \cdot (i - j). \end{cases} \]

\[\text{dp}[i][2] = \min \begin{cases} c_1 \cdot i + c_2, \\ \text{dp}[j][0] + c_1 \cdot (i - 1 - j) + c_2 \quad \text{if} \quad b_i \geq a_j \land a_i \geq b_j, \\ \text{dp}[j][2] + c_1 \cdot (i - 1 - j) + c_2 \quad \text{if} \quad b_i \geq b_j \land a_i \geq a_j. \end{cases} \]

最终答案为 \(\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}[i] = \max \begin{cases} \text{dp}[i-1], \\ a_i, \\ a_i + b_i \quad \text{if} \quad \text{dp}[i-1] \geq a_i. \end{cases} \]

最终答案为 \(\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 中国大陆许可协议进行许可。

posted @   Ke_scholar  阅读(15)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起