牛客周赛 Round 81
A. 麻将入门
题意:给你三个数,判断是不是相等或者连续的三个数。
点击查看代码
void solve() {
int a, b, c;
std::cin >> a >> b >> c;
if ((a == b && b == c) || (a + 1 == b && b + 1 == c)) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
B. 数数入门
题意:给你一个数字金字塔,判断是不是每个
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector a(n, std::vector<int>(n));
for (int i = 0; i < n; ++ i) {
for (int j = 0; j <= i; ++ j) {
std::cin >> a[i][j];
}
}
for (int i = 0; i + 1 < n; ++ i) {
for (int j = 0; j <= i; ++ j) {
if (a[i][j] > a[i + 1][j] || a[i][j] > a[i + 1][j + 1]) {
std::cout << "No\n";
return;
}
}
}
std::cout << "Yes\n";
}
C. 加法入门
题意:题意:给你一个数字金字塔,现在翻转了一个区间的数的位置,判断是不是每个
发现翻转区间的数超过两层肯定不行,都在一层一定可以,考虑横跨两层的情况,那么要让下面的数翻上去后下面没有从上面翻下去的数,那么翻转总数要小于等于下面这层的数的个数。
点击查看代码
void solve() {
i64 n;
std::cin >> n;
auto get = [&](i64 x) -> std::array<i64, 3> {
i64 l = 0, r = n;
while (l < r) {
i64 mid = l + r + 1 >> 1ll;
if (1 + mid * (mid + 1) / 2 <= x) {
l = mid;
} else {
r = mid - 1;
}
}
return {l, x - (1 + l * (l + 1) / 2) + 1, (1 + (l + 1) * (l + 2) / 2) - x};
};
i64 l, r;
std::cin >> l >> r;
auto a = get(l), b = get(r);
if (a[0] == b[0] || (a[0] + 1 == b[0] && a[2] + b[1] <= b[0])) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
}
D. 中场撸猫
题意:给你一个
每层都应该尽量选最小的一些数,那么可以对每一层数进行排序,然后下一场贪心的从小到大选数匹配上一场的。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector a(n, std::vector<int>(n));
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < n; ++ j) {
std::cin >> a[i][j];
}
std::sort(a[i].begin(), a[i].end());
}
std::vector<int> last;
last.push_back(a[0][0]);
for (int i = 1; i < n; ++ i) {
std::vector<int> b;
int j = 0;
for (int k = 0; j < i && k < n; ++ k) {
if (a[i][k] >= last[j]) {
b.push_back(a[i][k]);
++ j;
}
if (b.size() == i) {
if (k == n - 1) {
std::cout << i << "\n";
return;
}
b.push_back(a[i][k + 1]);
}
}
if (j < i) {
std::cout << i << "\n";
return;
}
last = b;
}
std::cout << n << "\n";
}
E. 建筑入门
题意:你要构造一个
正解是dp,但我爆搜过了,可能是数据水了。
搜索构造
点击查看代码
void solve() {
int n, k;
std::cin >> n >> k;
std::vector<i64> pre(k + 1);
for (int i = 1; i <= k; ++ i) {
pre[i] = (i64)i * i + pre[i - 1];
}
std::vector<int> ans, a;
auto dfs = [&](auto self, int n, int k, int m) -> void {
if (ans.size()) {
return;
}
if (n == 0 && k == 0) {
ans = a;
return;
}
if (n == 0 || k == 0 || m < n) {
return;
}
i64 sum = 0;
for (int i = n, x = m; i >= 1; -- i, -- x) {
sum += (i64)i * x;
}
if (sum < k) {
return;
}
sum = pre[n - 1];
int l = n, r = std::min(m, k / n);
while (l < r) {
int mid = l + r >> 1;
if (sum + (i64)mid * n >= k) {
r = mid;
} else {
l = mid + 1;
}
}
for (int i = l; i >= 1; -- i) {
a.push_back(i);
self(self, n - 1, k - i * n, i - 1);
a.pop_back();
}
};
dfs(dfs, n, k, k / n);
if (ans.empty()) {
std::cout << -1 << "\n";
return;
}
std::reverse(ans.begin(), ans.end());
for (auto & x : ans) {
std::cout << x << " \n"[ans.back() == x];
}
}
F. 拆迁入门
题意:一个按数字大小顺序放置的数字金字塔,然后拿走了
存每一层连续的数字,然后每层拿最大的区间,计算对下一个区间的贡献。
点击查看代码
void solve() {
i64 n, k;
std::cin >> n >> k;
std::vector<i64> a(k);
for (int i = 0; i < k; ++ i) {
std::cin >> a[i];
}
auto get = [&](i64 x) -> i64 {
i64 l = 0, r = n;
while (l < r) {
i64 mid = l + r + 1 >> 1ll;
if (1 + mid * (mid + 1) / 2 <= x) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
};
std::set<std::pair<i64, i64>> s;
std::sort(a.begin(), a.end());
for (int i = 0; i < k; ++ i) {
int j = i;
i64 id = get(a[i]);
i64 l = a[i], r = a[i];
while (j + 1 < k && a[j + 1] == a[j] + 1 && get(a[j + 1]) == id) {
++ j;
++ r;
}
i = j;
s.insert({l, r});
}
auto insert = [&](i64 l, i64 r) -> void {
if (l == r) {
return;
}
i64 id = get(l);
i64 x = l - id, y = r - id - 1;
while (s.size()) {
auto pre = s.lower_bound({x, y});
if (pre != s.begin()) {
-- pre;
if (pre->second >= x - 1 && get(pre->second) == get(x)) {
x = std::min(x, pre->first);
y = std::max(y, pre->second);
s.erase(pre);
} else {
break;
}
} else {
break;
}
}
while (s.size()) {
auto next = s.lower_bound({x, y});
if (next != s.end()) {
if (next->first <= y + 1 && get(next->first) == get(x)) {
x = std::min(x, next->first);
y = std::max(y, next->second);
s.erase(next);
} else {
break;
}
} else {
break;
}
}
s.insert({x, y});
};
i64 ans = 0;
while (s.size()) {
auto [l, r] = *s.rbegin();
s.erase({l, r});
// std::cout << l << " " << r << "\n";
ans += r - l + 1;
insert(l, r);
}
std::cout << ans << "\n";
}
分类:
牛客
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具