-------------------昨天打的重现赛,感觉是我打的发挥的最好的一场比赛了,六题都一次AC。那么就来总结一下吧
题目链接:http://codeforces.com/contest/1133
A .Middle of the Contest
sol:简单模拟,注意一下跨天的情况就好了。
- 模拟
#include "bits/stdc++.h" using namespace std; int main() { int h1, m1, h2, m2, k; scanf("%d:%d%d:%d", &h1, &m1, &h2, &m2); // 把第二个时间加24小时,就能保证第二个时间比第一个时间大 k = (m2 - m1 + (h2 + 24 - h1) * 60) % (24 * 60) >> 1; m1 += k; h1 = (h1 + m1 / 60) % 24; m1 %= 60; printf("%02d:%02d", h1, m1); return 0; }
B .Preparation for International Women's Day
sol:如果(a + b) % k == 0,那么(a % k) + (b % k) == 0 || (a % k) + (b % k) == k。注意等于0的情况不要忽略掉。遍历一遍,对于第d[i],查看是否在前面出现过还未配对的余数和d[i]余数相加等于0或k的情况。
- 同余
#include "bits/stdc++.h" using namespace std; const int MAXN = 105; int n, k, v, ans; int cnt[MAXN]; int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) { scanf("%d", &v); v %= k; if (cnt[(k - v) % k]) { ans += 2; cnt[(k - v) % k]--; } else { cnt[v]++; } } printf("%d\n", ans); return 0; }
C .Balanced Team
sol:尺取法,先排序,定义l = r = 1。然后让l和r一起往右移。
- 尺取法
#include "bits/stdc++.h" using namespace std; const int MAXN = 2e5 + 5; int arr[MAXN], n, ans; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &arr[i]); } sort(arr + 1, arr + 1 + n); int l = 1, r = 1; while (r <= n) { while (arr[r] - arr[l] > 5) l++; ans = max(ans, r - l + 1); r++; } printf("%d\n", ans); return 0; }
D .Zero Quantity Maximization
sol:首先换个姿势看这个问题,c[i] = d * a[i] + b[i],求c数组0最多有几个,那么我让题目变成c[i] = a[i]和b[i]的比。求相同比最多的次数。用map计数就行了。但是这个比不能用double来计,会产生精度丢失。所以我是用pair来计比的。还有就要说说这题的样例了,a[i] == 0这种属于特殊数据怎么能放到样例里呢,虽然我一开始也没考虑到。注意约分的时候a[i]为0的情况;
- 这题考细心
#include "bits/stdc++.h" using namespace std; typedef pair<int, int> PII; const int MAXN = 2e5 + 5; map<PII, int> mp; int a[MAXN], b[MAXN]; int ans, n, k, g; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= n; i++) scanf("%d", &b[i]); for (int i = 1; i <= n; i++) { if (a[i] == 0) { k += (b[i] == 0); continue; } g = __gcd(a[i], b[i]); a[i] /= g, b[i] /= g; mp[{a[i], b[i]}]++; ans = max(ans, mp[{a[i], b[i]}]); } printf("%d\n", ans + k); return 0; }
E .K Balanced Teams
sol:动态规划,先sort一下。dp[i][j]表示从第i个队员到最后一个队员组成j个队伍最多的人数。
ps:除了动态规划的部分,其他的和C题都一样。不过数据范围比较小,尺取法不是关键考点。用暴力也能过。
- 动态规划
#include "bits/stdc++.h" using namespace std; const int MAXN = 5005; int arr[MAXN]; int dp[MAXN][MAXN]; int ans; int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); sort(arr + 1, arr + 1 + n); for (int i = n; i >= 1; i--) { int k = i; while (k <= n && arr[k] - arr[i] <= 5) k++; for (int j = 1; j <= m; j++) { dp[i][j] = max(dp[i + 1][j], k - i + dp[k][j - 1]); ans = max(ans, dp[i][j]); } } printf("%d\n", ans); return 0; }
F1 .Spanning Tree with Maximum Degree
sol:找到度数最大的节点,以度数最大的节点为起点bfs遍历全图
- 图算法
#include "bits/stdc++.h" using namespace std; const int MAXN = 2e5 + 5; vector<int> edge[MAXN]; int maxdg, pos; bool use[MAXN]; void bfs(int pos) { queue<int> que; que.push(pos); use[pos] = true; while (!que.empty()) { pos = que.front(); que.pop(); for (int i = 0; i < edge[pos].size(); i++) { if (!use[edge[pos][i]]) { printf("%d %d\n", pos, edge[pos][i]); que.push(edge[pos][i]); use[edge[pos][i]] = true; } } } } int main() { int n, m, u, v; scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); edge[u].push_back(v); edge[v].push_back(u); if (edge[u].size() > maxdg) { maxdg = edge[u].size(); pos = u; } if (edge[v].size() > maxdg) { maxdg = edge[v].size(); pos = v; } } bfs(pos); return 0; }