The 18-th Beihang University Collegiate Programming Contest (BCPC 2023) - Final

https://codeforces.com/gym/104883

1|0A


#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using vi = vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); i64 n, sum = 0; cin >> n; for(int i = 1, x; i <= n ; i ++) cin >> x, sum += x; cout << max(0ll, sum); return 0; }

2|0B


#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int long long using vi = vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi a(n); for(auto &i : a) cin >> i; int m; cin >> m; vi b(m); for(auto &i : b) cin >> i; sort(b.begin(), b.end()); for(int i = 1; i <= m; i ++) b[i] += b[i-1]; for( int i = 0; i < n ; i ++) cout << upper_bound(b.begin(), b.end(), a[i]) - b.begin() << " "; return 0; }

3|0C


先说ba怎么满足,必定是有一个前缀和a完全相同,然后前缀后第一位a一定是1b0,再往后就可以随便取值了。这的话前缀内的异或值为 0,之后的异或值全部为1。所以可以二分最长的前缀,然后后缀的每一位都取反即可。这样的话异或后1的数量可能大于x,我们在后缀中从高位开始,尽可能的插入1就好了。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int long long using vi = vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); string s; int x; cin >> s >> x; if(x == 0) { cout << s; return 0; }else if(s.size() < x) { cout << -1; return 0; } vi pos; for(int i = 0; i < s.size(); i ++) if(s[i] == '1') pos.push_back(i); if(pos.empty()) { if(x > 0) cout << -1; else cout << 0; return 0; } int l = 0, r = pos.size() - 1, m = -1; auto check = [=](int a){ int c = s.size() - pos[a] - 1; return c >= x - 1; }; while (l <= r ) { int mid = (l + r) / 2; if(check(mid)) l = mid + 1, m = mid; else r = mid - 1; } string res; if(pos[m] != 0) res += s.substr(0, pos[m]) + "0"; string ans = s.substr(pos[m] + 1); for(auto &i: ans) { if(i == '0') i = '1'; else i = '0'; } for(int i = 0, cnt = ans.size() - x + 1; cnt > 0 and i < ans.size(); i ++ ) if(ans[i] == '0') ans[i] = '1', cnt --; res += ans; for(int i = 0; i < res.size(); i ++ ){ if(res[i] == '0') continue; cout << res.substr(i); return 0; } cout << 0; return 0; }

4|0D


一开始构造一个菊花图,然后对于每个点尽可能的插到最深的点上。

#include <bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, d; cin >> n >> d; if (d < (n - 1) or d > n * (n - 1) / 2) { cout << "NO\n"; return 0; } vi fa(n + 1); fa[2] = 1; int sum = n - 1; int top = 1; vi dep; dep.push_back(1), dep.push_back(2); for (int i = 3, l, r, res, mid; i <= n; i++) { l = 0, r = top, res = -1; while (l <= r) { mid = (l + r) / 2; if (sum + mid <= d) res = mid, l = mid + 1; else r = mid - 1; } sum += res, fa[i] = dep[res]; if (res == top) top++, dep.push_back(i); } cout << "YES\n"; for( int i = 2 ; i <= n ; i ++ ) cout << fa[i] << " " << i << "\n"; cout << "1\n"; return 0; }

5|0E


每次贪心的合并最小的两个或三个(相邻且相同的只有三个)是最优解。用set维护所有的区间的值和区间的大小即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int long long using vi = vector<int>; void solve() { int n; cin >> n; set<array<int,3>> q; for(int i = 1, x; i <= n; i ++) cin >> x, q.insert({x, i, i}); while(not q.empty()) { auto [x, l, r] = *q.begin(); q.erase(q.begin()); if(q.empty()){ cout << "Yes\n"; return; } if(q.begin()->at(0) == x and q.begin()->at(1) == r + 1 ){ r = q.begin()->at(2), q.erase(q.begin()); if(not q.empty() and q.begin()->at(0) == x and q.begin()->at(1) == r + 1){ if(q.size() == 1) { r = q.begin()->at(2) , q.erase(q.begin()); }else{ auto it = *next(q.begin()); if(it[0] != x or q.begin()->at(2) + 1 != it[1]) r = q.begin()->at(2), q.erase(q.begin()); } } q.insert({x + 1, l, r}); }else{ cout << "No\n"; return ; } } return; } i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for(cin >> TC; TC; TC --) solve(); return 0; }

6|0F


可以根据二分的过程,确定每个位置上数字的取值范围,我们把范围从小到大排序,然后对于每个范围,我们贪心的选择打满足这个范围的最大值。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int long long using vi = vector<int>; void solve() { int n, m; cin >> n >> m; vi p(n + 1, 1), q(n + 1, n + 1);// p[i] <= a[i] < q[i] for(int x, y, l, r, mid; m; m --){ cin >> x >> y, l = 1, r = n; while(l < r) { int mid = (l + r) / 2; if (mid < y) q[mid] = min(q[mid], x), l = mid + 1; else p[mid] = max(p[mid], x), r = mid; } } for(int i = 1; i <= n ; i ++ ){ if(p[i] < q[i]) continue; cout << "-1\n"; return; } vi res(n+1); set<int> s; for (int i = 1; i <= n; i ++ ) s.insert(i); vi a(n+1); iota(a.begin(), a.end(), 0); sort(a.begin() + 1, a.end(), [&](int i, int j){ if(q[i] - p[i] != q[j] - p[j]) return q[i] - p[i] < q[j] - p[j]; return p[i] > p[j]; }); for( int x = 1, i; x <= n; x ++) { i = a[x]; auto it = (s.lower_bound(q[i])); if(it == s.begin()) { cout << "-1\n"; return; } it = prev(it); if(*it >= p[i]) res[i] = *it, s.erase(it); else { cout << "-1\n"; return; } } for(int i = 1; i <= n ; i ++) cout << res[i] << " \n"[i == n]; return; } i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for(cin >> TC; TC; TC --) solve(); return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18150631.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(87)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示