Codeforces 比赛笔记(1)
1、Codeforces Round #775 (Div. 2, based on Moscow Open Olympiad in Informatics)
A
注意最多只能跳一次。
1 const int N = 110; 2 int t, n, l, r, a[N]; 3 4 int main() 5 { 6 read(t); 7 while (t--) 8 { 9 read(n); l = 1, r = n; 10 for (int i = 1; i <= n; ++i) read(a[i]); 11 while (l < n && a[l + 1]) ++l; 12 while (r > 1 && a[r - 1]) --r; 13 print(l > r ? 0 : r - l), pc('\n'); 14 } 15 fwrite(pbuf, 1, pp - pbuf, stdout); return 0; 16 }
B
考虑踢球次数最多的人没踢完的话剩下的球都得自己踢,踢完了剩下的人传着踢就行。
所以答案就是最大的 $a[i]$ 减去其他 $a[i]$ 后的值跟 $1$ 取 $\max$,注意特判全为 $0$ 的情况。
1 const int N = 1e5 + 10; 2 int t, n, a[N]; 3 4 int main() 5 { 6 read(t); 7 while (t--) 8 { 9 read(n); 10 for (int i = 1; i <= n; ++i) read(a[i]); 11 nth_element(a + 1, a + 1, a + n + 1, greater<int>()); 12 if (!a[1]) { pc('0'), pc('\n'); continue; } 13 for (int i = 2; i <= n; ++i) 14 { 15 a[1] -= a[i]; 16 if (a[1] < 1) break; 17 } 18 if (a[1] < 1) pc('1'), pc('\n'); 19 else print(a[1]), pc('\n'); 20 } 21 fwrite(pbuf, 1, pp - pbuf, stdout); return 0; 22 }
C
由于是曼哈顿距离,直接将答案拆成行和列的分别求解即可。
1 const int N = 1e5 + 10; 2 int n, m; 3 ll ans, cnt[N], sum[N]; 4 vector<int> a[320]; 5 6 int main() 7 { 8 read(n, m); 9 for (int x, i = 1; i <= n; ++i) 10 { 11 a[i].emplace_back(0); 12 for (int j = 1; j <= m; ++j) 13 read(x), a[i].emplace_back(x); 14 } 15 for (int i = 1; i <= n; ++i) 16 { 17 for (int j = 1; j <= m; ++j) 18 ans += cnt[a[i][j]] * i - sum[a[i][j]]; 19 for (int j = 1; j <= m; ++j) 20 ++cnt[a[i][j]], sum[a[i][j]] += i; 21 } 22 memset(cnt, 0, sizeof(cnt)); 23 memset(sum, 0, sizeof(sum)); 24 for (int j = 1; j <= m; ++j) 25 { 26 for (int i = 1; i <= n; ++i) 27 ans += cnt[a[i][j]] * j - sum[a[i][j]]; 28 for (int i = 1; i <= n; ++i) 29 ++cnt[a[i][j]], sum[a[i][j]] += j; 30 } 31 print(ans); 32 fwrite(pbuf, 1, pp - pbuf, stdout); return 0; 33 }
D
直接暴力枚举 $y$ 和 $\lfloor\dfrac{x}{y}\rfloor$,判断数组中是否存在 $x$ 但不存在 $\lfloor\dfrac{x}{y}\rfloor$ 即可。
由于枚举的是倍数关系,$\dfrac{n}{1}+\dfrac{n}{2}+\dfrac{n}{3}+\cdots+\dfrac{n}{n}=O(n\log{n})$,所以时间复杂度是正确的。
1 const int N = 1e6 + 10; 2 int t, n, c, a[N], cnt[N]; 3 4 inline bool check(int y) 5 { 6 for (int k = 1; k * y <= c; ++k) 7 { 8 int l = k * y - 1, r = Min(k * y + y - 1, c); 9 if (cnt[r] - cnt[l] && !(cnt[k] - cnt[k - 1])) return false; 10 } 11 return true; 12 } 13 14 int main() 15 { 16 read(t); 17 while (t--) 18 { 19 read(n, c); bool flag = true; 20 for (int i = 1; i <= n; ++i) read(a[i]), ++cnt[a[i]]; 21 for (int i = 1; i <= c; ++i) cnt[i] += cnt[i - 1]; 22 sort(a + 1, a + n + 1); 23 for (int i = 1; i <= n; ++i) 24 if (a[i] != a[i - 1] && !check(a[i])) { flag = false; break; } 25 puts(flag ? "Yes" : "No"); 26 for (int i = 1; i <= c; ++i) cnt[i] = 0; 27 } 28 fwrite(pbuf, 1, pp - pbuf, stdout); return 0; 29 }
E
F
2、Codeforces Round #776 (Div. 3)
A
判奇偶性即可。
1 int main() 2 { 3 int t; read(t); 4 while (t--) 5 { 6 int n; char s[50], c; bool flag = false; 7 read(s + 1), n = strlen(s + 1), read(c); 8 for (int i = 1; i <= n; ++i) 9 if (s[i] == c && !(i - 1 & 1) && !(n - i & 1)) 10 { flag = true; break; } 11 puts(flag ? "YES" : "NO"); 12 } 13 flush_pbuf(); return 0; 14 }
B
讨论 $\lfloor\dfrac{x}{a}\rfloor$ 与 $x\bmod a$ 最大即可。
1 inline int f(int x, int a) { return x / a + x % a; } 2 3 int main() 4 { 5 int t; read(t); 6 while (t--) 7 { 8 int l, r, a; read(l, r, a); 9 print(Max(f(r, a), f(Max(l, r - r % a - 1), a))), pc('\n'); 10 } 11 flush_pbuf(); return 0; 12 }
C
答案只跟点权之和有关,直接取最小点权即可。
1 const int N = 2e5 + 10; 2 struct node { int x, w, id; } a[N]; 3 4 inline bool cmp1(const node &x, const node &y) { return x.w < y.w; } 5 inline bool cmp2(const node &x, const node &y) { return x.x < y.x; } 6 7 int main() 8 { 9 int t; read(t); 10 while (t--) 11 { 12 int n, m, ans = 0; read(n, m); 13 for (int i = 1; i <= m; ++i) read(a[i].x, a[i].w), a[i].id = i; 14 sort(a + 1, a + m + 1, cmp1); 15 for (int i = 1; i <= n << 1; ++i) ans += a[i].w; 16 print(ans, '\n'); sort(a + 1, a + (n << 1) + 1, cmp2); 17 for (int i = 1; i <= n; ++i) 18 print(a[i].id, ' ', a[(n << 1) - i + 1].id, '\n'); 19 } 20 flush_pbuf(); return 0; 21 }
D
直接用递归倒推还原即可。
1 const int N = 4e3 + 10; 2 int a[N], b[N], d[N]; 3 4 void solve(int n) 5 { 6 if (n == 1) return; 7 for (int i = 1; i <= n; ++i) b[i] = b[n + i] = a[i]; 8 int pos; 9 for (int i = n; i < n << 1; ++i) 10 if (b[i] == n) { pos = i; break; } 11 d[n] = pos - n; 12 for (int i = 1; i < n; ++i) a[i] = b[pos - n + i]; 13 solve(n - 1); 14 } 15 16 int main() 17 { 18 int t; read(t); 19 while (t--) 20 { 21 int n; read(n); 22 for (int i = 1; i <= n; ++i) read(a[i]); 23 solve(n); 24 for (int i = 1; i <= n; ++i) print(d[i]), pc(' '); pc('\n'); 25 } 26 flush_pbuf(); return 0; 27 }
E
用一个支持插入删除查询最小最大值的数据结构,注意特判删最后一个点的情况。
1 const int N = 2e5 + 10; 2 int a[N]; 3 multiset<int> s; 4 5 int main() 6 { 7 int t; read(t); 8 while (t--) 9 { 10 int n, d, ans; read(n, d); ans = 0; 11 for (int i = 1; i <= n; ++i) read(a[i]); 12 for (int i = 1; i <= n; ++i) s.insert(a[i] - a[i - 1] - 1); 13 for (int i = 1; i < n; ++i) 14 { 15 auto it = s.lower_bound(a[i] - a[i - 1] - 1); s.erase(it); 16 it = s.lower_bound(a[i + 1] - a[i] - 1), s.erase(it); 17 s.insert(a[i + 1] - a[i - 1] - 1); 18 ans = Max(ans, Min(*s.begin(), Max(*--s.end() - 1 >> 1, d - a[n] - 1))); 19 it = s.lower_bound(a[i + 1] - a[i - 1] - 1), s.erase(it); 20 s.insert(a[i] - a[i - 1] - 1), s.insert(a[i + 1] - a[i] - 1); 21 } 22 auto it = s.lower_bound(a[n] - a[n - 1] - 1); s.erase(it); 23 ans = Max(ans, Min(*s.begin(), Max(*--s.end() - 1 >> 1, d - a[n - 1] - 1))); 24 print(ans), pc('\n'); multiset<int>().swap(s); 25 } 26 flush_pbuf(); return 0; 27 }
F
G
3、Educational Codeforces Round 124 (Rated for Div. 2)
4、Codeforces Round #777 (Div. 2)
To be continued...