ZZJC 2024 autumn Team Contest - 11题解
链接:https://codeforces.com/group/sqkBGLC2jv/contest/567721
A-解题思路
(800)按照题意模拟即可
A-代码实现
for _ in range(int(input())):
n = list(map(int, list(input())))
if sum(n[:3]) * 2 == sum(n):
print("YES")
else:
print("NO")
B-解题思路
(800)范围很小,暴力枚举即可
B-代码实现
for _ in range(int(input())):
n, m = map(int, input().split())
s = []
for i in range(n):
s.append(input())
ans = float("inf")
for i in range(n):
for j in range(n):
t = float("inf")
if i != j:
t = 0
for k in range(m):
t += min(ans, abs(ord(s[i][k]) - ord(s[j][k])))
ans = min(ans, t)
print(ans)
C-解题思路
(1100)要最少显然越大的越先吃,降序后前缀和预处理,二分取第一个大于x的位置即可
C-代码实现
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
int n ,q;
std::cin >> n >> q;
std::vector<int> a(n), pre(n + 1);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::sort(a.begin(), a.end(), std::greater<int>());
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + a[i - 1];
}
while (q--) {
int x;
std::cin >> x;
auto pos = std::lower_bound(pre.begin(), pre.end(), x);
if (pos != pre.end()) {
std::cout << pos - pre.begin() << "\n";
} else {
std::cout << -1 << "\n";
}
}
}
}
E-解题思路
(1300)先统计所有数字的数量,然后双指针扫描(注意这里的lr是值而非位置),t里面放的是出现次数大于等于k的数字,用于维护最大区间,也就是连续的值,某个具体值出现的次数大于k,看这个连续部分最多能有多长
E-代码实现
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int T;
std::cin >> T;
while (T--) {
int n, k, l = 0, r = 0;
std::cin >> n >> k;
std::map<int, int> mp;
std::vector<int> a(n), t;
for (int i = 0; i < n; i++) {
std::cin >> a[i];
mp[a[i]]++;
}
for (auto [i, j]: mp) {
if (j >= k) {
if (t.empty() || i - 1 <= t.back()) {
t.push_back(i);
} else {
if (!t.empty() && t.back() - t.front() >= r - l) {
l = t.front();
r = t.back();
}
t.clear();
t.push_back(i);
}
} else {
if (!t.empty() && t.back() - t.front() >= r - l) {
l = t.front();
r = t.back();
}
t.clear();
}
}
if (!t.empty() && t.back() - t.front() >= r - l) {
l = t.front();
r = t.back();
}
if (r) {
std::cout << l << " " << r << "\n";
} else {
std::cout << -1 << "\n";
}
}
}
F-解题思路
(1300)dfs从根节点开始扫一遍并根据节点颜色对平衡值bal进行修改,某一部分的bal如果是0则说明这一部分是平衡的,直接对答案+1即可
F-代码实现
#include <bits/stdc++.h>
const int N = 4e3 + 10;
std::vector<int> g[N];
std::string s;
int dfs(int x, int &res) {
int bal = (s[x - 1] == 'B') ? -1 : 1;
for (int i : g[x]) {
bal += dfs(i, res);
}
if (bal == 0) {
res++;
}
return bal;
}
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
for (int i = 0; i < N; ++i) {
g[i].clear();
}
int n;
std::cin >> n;
for (int i = 2; i <= n; i++) {
int x;
std::cin >> x;
g[x].push_back(i);
}
std::cin >> s;
int res = 0;
dfs(1, res);
std::cout << res << "\n";
}
}
G-解题思路
(1700)这一题其实就是要找一个区间,让其中相同的数字尽可能的多,先记录这个数字的所有位置,然后滑动窗口扫描这个数字出现的位置并贪心即可
G-代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
i64 n, maxn = 0, ans = 0, ansl = 0, ansr = 0;
std::cin >> n;
std::map<int, std::vector<int>> mp;
for (int i = 1; i <= n; i++) {
int x;
std::cin >> x;
mp[x].push_back(i);
}
for (auto [x, v] : mp) {
int l = 0, r = 0, len = 1, maxlen = 1, L = v[0], R = v[0];
while (r + 1 < v.size()) {
if (v[r + 1] - v[r] == 1) { // 连续直接增加
len++;
} else {
len -= (v[r + 1] - v[r] - 2); // 不连续的时候需要减去的代价
if (len <= 0) { // 如果代价太大则直接重置起点
len = 1;
l = r + 1;
}
}
r++;
if (len > maxlen) {
maxlen = len;
L = v[l];
R = v[r];
}
}
if (maxlen > maxn) {
maxn = maxlen;
ans = x;
ansl = L;
ansr = R;
}
}
std::cout << ans << " " << ansl << " " << ansr << "\n";
}
}
H-解题思路
(1400)题目的意思就是找一个区间,对区间内的每个数乘上2的索引次后还要是个升序区间,由于是一个连续区间,所以只需要看相邻的倍数关系就知道是否符合要求,统计范围内符合长度的区间数量即可
H-代码实现
for _ in range(int(input())):
n, k = map(int, input().split())
a = list(map(int, input().split()))
ans = 0
t = 1
for i in range(1, n):
if a[i - 1] < a[i] * 2:
t += 1
else:
t = 1
if t >= k + 1:
ans += 1
print(ans)
I-解题思路
(1100)赤石题,模拟一下
I-代码实现
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
std::vector<int> time(4);
std::set<int> ans;
for (int i = 0; i < 4; i++) {
char c;
std::cin >> c;
if (c == ':') {
i--;
} else {
time[i] = c - '0';
}
}
int x;
std::cin >> x;
for (int i = 0; i < 1440; i++) { // 一天最多1440分钟,枚举一天的时间即可
if (time[0] == time[3] && time[1] == time[2]) {
ans.insert(time[0] * 1000 + time[1] * 100 + time[2] * 10 + time[3]);
}
time[3] += x;
time[2] += time[3] / 10;
time[3] = time[3] % 10;
time[1] += time[2] / 6;
time[2] = time[2] % 6;
time[0] += time[1] / 10;
time[1] = time[1] % 10;
while (time[0] * 10 + time[1] >= 24) {
time[0] -= 2;
time[1] -= 4;
}
}
std::cout << ans.size() << "\n";
}
}
# 日历时间类的题目py也很有优势
from datetime import datetime, timedelta
for _ in range(int(input())):
s, x = input().split()
x = int(x)
st = set()
now = datetime.strptime(s, "%H:%M")
for i in range(1440):
S = now.strftime("%H:%M")
if S == S[::-1]:
st.add(S)
now += timedelta(minutes = x)
if S == s:
break
print(len(st))
J-解题思路
(1200)前缀和预处理后二分要删除的位置,枚举左端点即可
J-代码实现
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
int n, s, ans = 1e9;
std::cin >> n >> s;
std::vector<int> a(n + 1), pre(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
pre[i] = pre[i - 1] + a[i];
}
for (int i = 1; i <= n; i++) {
int l = i, r = n;
while (l <= r) {
int mid = (l + r) / 2;
if (pre[mid] - pre[i - 1] <= s) {
l = mid + 1;
} else {
r = mid - 1;
}
}
if (pre[r] - pre[i - 1] == s) {
ans = std::min(ans, n - (r - i + 1));
}
}
if (ans != 1e9) {
std::cout << ans << "\n";
} else {
std::cout << -1 << "\n";
}
}
}

浙公网安备 33010602011771号