復健,時間有限題解比較簡陋node
將小時轉成分鐘,獲得起止時間在一天中的分鐘數,取平均值便可,複雜度O(1)
。平均值轉換會時間的時候注意前導0。ios
void solve(int x) { x /= 2; printf("%02d:%02d\n", x / 60, x % 60); } int main() { // freopen("in.txt", "r", stdin); // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)cpp; int h1, h2, m1, m2; char c; cin >> h1 >> c >> m1; cin >> h2 >> c >> m2; solve(h1 * 60 + m1 + h2 * 60 + m2); }
要加起來能被k
整除, 只須要看模k
的餘數便可。餘數爲i
的與餘數爲k-i
的互補能夠被k
整除,經過計數看有多少對能互補。須要注意的是,爲餘數爲0
和k/2
(k爲偶數)時,只能同餘數的互補,此時計數是偶數個時都能配對,奇數個時能配對的數量是計數 - 1。複雜度O(n + k)
。c++
int main() { // freopen("in.txt", "r", stdin); ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n, k, x, cnt = 0; cin >> n >> k; int d[k] = {0}; for (int i = 0; i < n; ++i) cin >> x, d[x % k]++; for (int i = 0; i < (k + 1) / 2; ++i) { if (i == 0) cnt += d[i] / 2; else { cnt += min(d[i], d[k - i]); } } if (k % 2 == 0) cnt += d[k / 2] / 2; cout << cnt * 2; }
單調隊列,從小到大添加元素,保證隊首和隊尾差不超過5,超過了則出隊,不然用當前隊列大小更新最優解。若是元素x < y
則x
必定比y
先入隊,並且能與x
共存的最小值sx
和能與y
共存的最小值sy
有sx <= sy
。使用單調隊列,每次入隊後進行出隊操做,出隊完成後隊首就是能與入隊元素共存的最小值,隊列內的元素就是以入隊元素爲最大值時全部能存在的元素。複雜度O(n)
數組
int main() { // freopen("in.txt", "r", stdin); ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n; cin >> n; ll a[n + 1]; for (int i = 1; i <= n; ++i) cin >> a[i]; sort(a + 1, a + 1 + n); int cnt = 0, l = 1, r = 2; while (l <= r && r <= n) { if (a[r] - a[l] > 5) cnt = max(cnt, r - l), l++; r++; } cnt = max(cnt, r - l); cout << cnt; }
d * a[i] + b[i] = 0
可得d = - b[i] / a[i]
,統計每種d
取值的個數,取最大便可。對於a[i]
爲0
的狀況須要特殊討論,若是b[i]
也爲0
則此時d
能夠取任意值;不然,d
的取值爲0
。另外,爲了不浮點偏差,不能直接統計d
,而是要統計<a, b>
這個配對;同時,爲了歸一化,須要將a
與b
同時除以他們的最大公約數,並保證a
是正數。複雜度O(nlog(n))
,log
是由於用了map
來計數。spa
// Author : RioTian // Time : 20/11/10 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 10; int main() { // freopen("in.txt", "r", stdin); ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n; cin >> n; ll a[n + 1], b[n + 1]; for (int i = 0; i < n; ++i) { cin >> a[i]; } for (int i = 0; i < n; ++i) { cin >> b[i]; } int zeroBCnt = 0, zeroBothCnt = 0; map<pair<int, int>, int> hash; for (int i = 0; i < n; ++i) { if (a[i] == 0) { if (b[i] == 0) ++zeroBothCnt; continue; } if (b[i] == 0) { ++zeroBCnt; } int divisor = gcd(abs(a[i]), abs(b[i])); a[i] /= divisor; b[i] /= divisor; if (a[i] < 0) { a[i] = -a[i]; b[i] = -b[i]; } if (hash[make_pair(a[i], b[i])]) ++hash[make_pair(a[i], b[i])]; else hash[make_pair(a[i], b[i])] = 1; } int ans = zeroBCnt; for (auto item : hash) { if (item.second > ans) ans = item.second; } cout << ans + zeroBothCnt << endl; return 0; }
與C題思路相似,先獲得取每一個元素爲最大值,能共存的元素有哪些(排過序的數組保留首位指針便可),好比位置爲i
的元素最小可共存元素的位置是maxStart[i]
,這樣數組裏面maxStart[i]
到i
都是可共存元素。問題就轉成如何在裏面選k
個,讓元素儘可能多,這樣dp便可。dp[i][j]
表示前i
個元素選j
隊的最優值,則若是選maxStart[i]
到i
,最優值爲dp[maxStart[i] - 1], j - 1] + i - maxStart[i] + 1
;若是不選,最優值爲dp[i - 1][j]
;二者取最優獲得狀態轉移方程。另外因爲j
只會從j - 1
轉移,所以能夠用滾動數組節約內存。複雜度O(nk)
。指針
// Author : RioTian // Time : 20/11/10 #include <bits/stdc++.h> using namespace std; const int N = 5e3 + 10; int a[N], maxStart[N], dp[N][2]; int n, k; int main() { cin >> n >> k; for (int i = 0; i < n; ++i) cin >> a[i]; sort(a, a + n); int l = 0, r = 0; while (r < n) { if (a[r] - a[l] <= 5) { maxStart[r] = l, ++r; continue; } ++l; } for (int i = 1; i <= k; ++i) { for (int j = 0; j < n; ++j) { if (maxStart[j]) { dp[j][i % 2] = max(dp[j - 1][i % 2], dp[maxStart[j] - 1][(i - 1) % 2] + j - maxStart[j] + 1); continue; } dp[j][i % 2] = max(dp[j - 1][i % 2], j - maxStart[j] + 1); } } cout << dp[n - 1][k % 2] << endl; return 0; }
直接找到度最大的節點bfs便可,複雜度O(n + m)
。code
#include <iostream> #include <queue> #include <vector> using namespace std; vector<int> node[200010]; bool visited[200010]; void bfs(int start) { queue<int> qu; qu.push(start); visited[start] = true; while (qu.size()) { int cur = qu.front(); qu.pop(); for (auto next : node[cur]) { if (visited[next]) continue; visited[next] = true; qu.push(next); cout << cur + 1 << ' ' << next + 1 << endl; } } } int main() { int n, m, x, y, tmp, maxCnt = 0, maxNode = -1; cin >> n >> m; for (int i = 0; i < m; ++i) { cin >> x >> y; --x; --y; node[x].push_back(y); node[y].push_back(x); tmp = node[x].size() > node[y].size() ? x : y; if (node[tmp].size() > maxCnt) { maxCnt = node[tmp].size(); maxNode = tmp; } } bfs(maxNode); return 0; }
若是從1
的一個分支出發能從另外一個分支回到1
,則這些分支劃分爲同一組,dfs便可獲得這些分組。若是一組裏面全部分支都被去掉了,則這組裏面的節點就沒法出如今樹裏面,所以至少要保留一個。dfs獲得有多少這樣的組,每組裏面取一個分支,剩下還能夠取則任意取。這些分支做爲bfs的第一步,繼續搜下去,按搜索順序輸出便可。非法的狀況有:dfs時存在節點沒有走到;須要的度數比組數少(此時至少有一組全部分支都被去掉);須要的度數比1
連接的分支多。複雜度O(n + m)
。隊列
#include <cstring> #include <iostream> #include <queue> #include <vector> using namespace std; bool visited[200010]; vector<int> node[200010]; vector<int> group[200010]; queue<int> qu; int n, m, d, g; void dfs(int cur, int parent) { visited[cur] = true; for (auto next : node[cur]) { if (visited[next]) { if (parent == -1) group[g - 1].push_back(next); continue; } if (parent == -1) { group[g++].push_back(next); } dfs(next, cur); } } void bfs() { while (qu.size()) { int cur = qu.front(); qu.pop(); for (auto next : node[cur]) { if (!visited[next]) { visited[next] = true; cout << cur + 1 << ' ' << next + 1 << endl; qu.push(next); } } } } int main() { int x, y; cin >> n >> m >> d; for (int i = 0; i < m; ++i) { cin >> x >> y; --x; --y; node[x].push_back(y); node[y].push_back(x); } memset(visited, 0, sizeof(visited)); dfs(0, -1); for (int i = 0; i < n; ++i) { if (!visited[i]) { cout << "NO" << endl; return 0; } } if (g > d || node[0].size() < d) { cout << "NO" << endl; return 0; } cout << "YES" << endl; memset(visited, 0, sizeof(visited)); visited[0] = true; d -= g; for (int i = 0; i < g; ++i) { cout << '1' << ' ' << group[i][0] + 1 << endl; visited[group[i][0]] = true; qu.push(group[i][0]); for (int j = 1; d && j < group[i].size(); ++j) { cout << '1' << ' ' << group[i][j] + 1 << endl; visited[group[i][j]] = true; qu.push(group[i][j]); --d; } } bfs(); return 0; }