2025/8/2 模拟赛总结
\(50+100+20+20=190\),第一题真的太抽象了
比较抽象的题,显然在确定箱子大小确定后,可以 \(O(nk)\) 暴力 check,写个暴力打表发现答案大概有单调性,但是直接二分可以过所有大样例且过 \(10^4\) 组拍。
这时可以在二分出答案后向前寻找 \(300\) 个,找到答案直接输出即可
// BLuemoon_
#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 1e3 + 5;
int T = 1, n, a[kMaxN], ans, k, L, R, cnt, vis[kMaxN], F = 1;
bool Chk(int x) {
fill(vis + 1, vis + n + 1, 0);
for (int i = 1; i <= k; i++) {
int lst = x;
for (int j = 1; j <= n; j++) {
lst >= a[j] && !vis[j] && (vis[j] = 1, lst -= a[j]);
}
}
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
return 0;
}
}
return 1;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
for (cin >> T; T; T--, cnt = 0, F = 1) {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i], cnt += a[i], i > 1 && (F &= a[i] == a[i - 1]);
}
if (k == 1) {
cout << cnt << '\n';
continue;
}
if (F) {
cout << (n + k - 1) / k * a[1] << '\n';
continue;
}
if (1ll * n * k * cnt <= 1e7) {
sort(a + 1, a + n + 1, greater<int>());
for (int i = 1; i <= cnt; i++) {
if (Chk(i)) {
ans = i;
break;
}
}
cout << ans << '\n';
continue;
}
sort(a + 1, a + n + 1, greater<int>()), L = 1, R = cnt;
for (int mid = L + R >> 1; L < R; mid = L + R >> 1) {
Chk(mid) ? R = mid : L = mid + 1;
}
for (int i = max(1, L - 300); i <= L; i++) {
if (Chk(i)) {
ans = i;
break;
}
}
cout << ans << '\n';
}
return 0;
}
这个是真的简单题,正难则反。将所有问号填入 \(1\),求出答案。对于每一个连续的问号段,如果左右字符不同则修改不影响答案。如果左右都是 \(0\),则答案会减少 \(2\),按长度从小到大会更优。否则如果两边都是 \(1\),则答案会增加 \(2\),此时按长度从大到小会更优。使用 set 模拟即可
// BLuemoon_
#include <bits/stdc++.h>
using namespace std;
using Pii = pair<int, int>;
const int kMaxN = 2e5 + 5;
struct Cmp {
bool operator()(const Pii &x, const Pii &y) const { return x.first != y.first ? x.first < y.first : (x.first == -2 ? x.second < y.second : (x.first == 2 ? x.second > y.second : x.second < y.second)); }
};
int T = 1, n, tot1, totq, ans[kMaxN], cur, cnt;
string s, t;
multiset<Pii, Cmp> st;
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
for (cin >> T; T; T--, tot1 = totq = 0, st.clear()) {
cin >> n >> s, s = ' ' + s, fill(ans, ans + n + 1, -1), t = s, cnt = 0;
for (int i = 1; i <= n; i++) {
tot1 += s[i] == '1', totq += s[i] == '?', t[i] == '?' && (t[i] = '1');
}
for (int i = 1, pre = 1; i <= n; i++) {
if (s[i] != '?') {
if (pre <= i - 1) {
if (s[pre - 1] != s[i]) {
st.insert({0, i - pre});
} else if (s[i] == '0') {
st.insert({-2, i - pre});
} else {
st.insert({2, i - pre});
}
}
pre = i + 1;
}
}
for (int i = 1; i <= n; i++) {
cnt += t[i] != t[i - 1];
}
ans[cur = totq + tot1] = cnt;
for (auto u : st) {
if (u.first == -2) {
for (int i = 1; i < u.second; i++) {
ans[--cur] = cnt;
}
ans[--cur] = (cnt -= 2);
} else if (u.first == 0) {
for (int i = 1; i <= u.second; i++) {
ans[--cur] = cnt;
}
} else {
ans[--cur] = (cnt += 2);
for (int i = 2; i <= u.second; i++) {
ans[--cur] = cnt;
}
}
}
for (int i = 0; i <= n; i++) {
cout << ans[i] << " \n"[i == n];
}
}
return 0;
}
TBD...
TBD...

浙公网安备 33010602011771号