A. Content Too Large
签到,计算出来物品体积的总和,与袋子的大小做对比即可。
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <bits/stdc++.h> #define x first #define y second #define endl '\n' using namespace std;using ll = long long ;using PII = pair<int , int >;int read () {int x = 0 , f = 1 ;char ch = getchar ();while (ch < '0' || ch > '9' ){if (ch == '-' ) f = -1 ;ch = getchar ();}while (ch >= '0' && ch <= '9' ){x = x * 10 + ch - '0' ;ch = getchar ();}return x * f;}void print (int x) {if (x < 0 ){putchar ('-' );x = -x;}if (x > 9 ) print (x / 10 );putchar (x % 10 + '0' );}void solve () { int n, m; cin >> n >> m; while (n--) { int x; cin >> x; m -= x; } if (m >= 0 ) cout << "Yes" << endl; else cout << "No" << endl; } int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int T = 1 ; while (T--) { solve (); } return 0 ; }
B. cat 2
枚举每一种拼接情况,因为 \(set\) 可以自动去重,可以考虑使用 \(set\) 存储拼接后的字符串,最后输出 \(s.size()\) 即为答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include <bits/stdc++.h> #define x first #define y second #define endl '\n' using namespace std;using ll = long long ;using PII = pair<int , int >;int read () {int x = 0 , f = 1 ;char ch = getchar ();while (ch < '0' || ch > '9' ){if (ch == '-' ) f = -1 ;ch = getchar ();}while (ch >= '0' && ch <= '9' ){x = x * 10 + ch - '0' ;ch = getchar ();}return x * f;}void print (int x) {if (x < 0 ){putchar ('-' );x = -x;}if (x > 9 ) print (x / 10 );putchar (x % 10 + '0' );}void solve () { int n; cin >> n; vector<string> a (n) ; for (int i = 0 ; i < n; i++) cin >> a[i]; set<string> s; for (int i = 0 ; i < n; i++) for (int j = 0 ; j < n; j++) if (i != j) s.insert (a[i] + a[j]); cout << s.size () << endl; } int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int T = 1 ; while (T--) { solve (); } return 0 ; }
C. Large Queue
由于插入和删除的数量级很大,如果每次只操作一个数的话,显然超时。
因此,我们可以考虑每次插入和删除的时候,操作一组数。
定义一个双端队列 \(deque\) ,类型为 \(pair<int, int>\) ,第一个元素代表个数,第二个元素代表大小。
操作 \(1\) ,直接插入 \(\{c,x\}\) ,代表我插入了 \(c\) 个 \(x\) ,复杂度为 \(O(1)\) 。
操作 \(2\) ,在取够 \(k\) 个数之前,我们每次从队列中取出的都是一组数,取出组数的上限是我们插入的组数,也就是说我们插入多少次,最多就取出多少次。由于插入的次数不超过 \(2 \times 10^5\) ,因此取出的总次数也不超过 \(2 \times 10^5\) ,不会超时。
需要注意的是答案有可能会超出 \(int\) 的范围,需要使用 \(long\ long\) 。
时间复杂度 \(O(Q)\) 。
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <bits/stdc++.h> #define x first #define y second #define endl '\n' using namespace std;using ll = long long ;using PII = pair<int , int >;int read () {int x = 0 , f = 1 ;char ch = getchar ();while (ch < '0' || ch > '9' ){if (ch == '-' ) f = -1 ;ch = getchar ();}while (ch >= '0' && ch <= '9' ){x = x * 10 + ch - '0' ;ch = getchar ();}return x * f;}void print (int x) {if (x < 0 ){putchar ('-' );x = -x;}if (x > 9 ) print (x / 10 );putchar (x % 10 + '0' );}void solve () { int n; cin >> n; deque<PII> q; while (n--) { int op; cin >> op; if (op == 1 ) { int c, x; cin >> c >> x; q.push_back ({c, x}); } else { int k; cin >> k; ll res = 0 ; while (k) { auto t = q.front (); q.pop_front (); if (t.x > k) { res += (ll)t.y * k; t.x -= k; k = 0 ; q.push_front (t); } else { res += (ll)t.x * t.y; k -= t.x; } } cout << res << endl; } } } int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int T = 1 ; while (T--) { solve (); } return 0 ; }
D. Make Geometric Sequence
对于一个等比数列,其中的元素一定满足它们的绝对值是有序的。
因此可以分两种情况讨论。
数组中的元素都是同号。此时判断排序后的数组能否构成等比数列即可。
数组中的元素有正有负。那么若要使这个数组构成等比数列,一定要使得其中的元素是一正一负排列,把正数和复数单独分离出来排列即可。
判断数组是否能构成等比数列,为避免出现小数,可以使用 \(a_i \times a_i=a_{i-1} \times a_{i+1}\) 作为判断条件。
时间复杂度 \(O(nlogn)\)
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 #include <bits/stdc++.h> #define x first #define y second #define endl '\n' using namespace std;using ll = long long ;using PII = pair<int , int >;int read () {int x = 0 , f = 1 ;char ch = getchar ();while (ch < '0' || ch > '9' ){if (ch == '-' ) f = -1 ;ch = getchar ();}while (ch >= '0' && ch <= '9' ){x = x * 10 + ch - '0' ;ch = getchar ();}return x * f;}void print (int x) {if (x < 0 ){putchar ('-' );x = -x;}if (x > 9 ) print (x / 10 );putchar (x % 10 + '0' );}void solve () { int n; cin >> n; vector<ll> a (n) ; for (int i = 0 ; i < n; i++) cin >> a[i]; auto cmp = [&](int A, int B) { return abs (A) < abs (B); }; sort (a.rbegin (), a.rend (), cmp); vector<ll> s1, s2; for (int i = 0 ; i < n; i++) { if (a[i] < 0 ) s1. push_back (a[i]); else s2. push_back (a[i]); } if (s1. size () && s2. size () && abs ((int )s1. size () - (int )s2. size ()) > 1 ) { cout << "No" << endl; return ; } vector<ll> s; if (!s1. size ()) { while (s2. size ()) { s.push_back (s2. back ()); s2. pop_back (); } } if (!s2. size ()) { while (s1. size ()) { s.push_back (s1. back ()); s1. pop_back (); } } if (s1. size () && s2. size ()) { bool flag = false ; if (s1. size () < s2. size ()) flag = true ; else if (s1. size () == s2. size () && abs (s2. back ()) < abs (s1. back ())) flag = true ; for (int i = 0 ; i < n; i++) { if (i % 2 == flag) { s.push_back (s1. back ()); s1. pop_back (); } else { s.push_back (s2. back ()); s2. pop_back (); } } } for (int i = 1 ; i < n - 1 ; i++) if (s[i] * s[i] != s[i - 1 ] * s[i + 1 ]) { cout << "No" << endl; return ; } cout << "Yes" << endl; } int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int T = 1 ; cin >> T; while (T--) { solve (); } return 0 ; }
E. Reverse 2^i
本场最有意思的题目,可以先操作小区间,再操作大区间,具体实现方法类似于归并排序。
时间复杂度 \(O(nlogn)\) 。
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #include <bits/stdc++.h> #define x first #define y second #define endl '\n' using namespace std;using ll = long long ;using PII = pair<int , int >;int read () {int x = 0 , f = 1 ;char ch = getchar ();while (ch < '0' || ch > '9' ){if (ch == '-' ) f = -1 ;ch = getchar ();}while (ch >= '0' && ch <= '9' ){x = x * 10 + ch - '0' ;ch = getchar ();}return x * f;}void print (int x) {if (x < 0 ){putchar ('-' );x = -x;}if (x > 9 ) print (x / 10 );putchar (x % 10 + '0' );}void solve () { int n; cin >> n; n = 1 << n; vector<int > a (n) ; for (int i = 0 ; i < n; i++) cin >> a[i]; function<void (int , int )> calc = [&](int l, int r) { if (l == r) return ; int mid = l + r >> 1 ; calc (l, mid), calc (mid + 1 , r); if (a[l] > a[mid + 1 ]) { for (int i = l, j = mid + 1 ; i <= mid; i++, j++) { swap (a[i], a[j]); } } }; calc (0 , n - 1 ); for (int i = 0 ; i < n; i++) cout << a[i] << ' ' ; cout << endl; } int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int T = 1 ; cin >> T; while (T--) { solve (); } return 0 ; }
F. No Passage
对于以当前格子为起点,其答案取决于上下左右四个格子的答案,由于青木会限制最小答案的方向,因此该起点的答案为上下左右四个方向答案的次小值加一。
考虑使用 \(bfs\) 来解决问题,对于每个终点都做一遍 \(bfs\) ,当某一个点第二次被更新到的时候,代表此时更新的距离为这个点到终点的次小值(第一次更新到的时候是最小值)。
时间复杂度 \(O(nm)\) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <bits/stdc++.h> #define x first #define y second #define endl '\n' using namespace std;using ll = long long ;using PII = pair<int , int >;int read () {int x = 0 , f = 1 ;char ch = getchar ();while (ch < '0' || ch > '9' ){if (ch == '-' ) f = -1 ;ch = getchar ();}while (ch >= '0' && ch <= '9' ){x = x * 10 + ch - '0' ;ch = getchar ();}return x * f;}void print (int x) {if (x < 0 ){putchar ('-' );x = -x;}if (x > 9 ) print (x / 10 );putchar (x % 10 + '0' );}void solve () { int n, m, k; cin >> n >> m >> k; vector c (n + 1 , vector<int >(m + 1 , 0 )) ; vector f (n + 1 , vector<int >(m + 1 , -1 )) ; queue<PII> q; while (k--) { int x, y; cin >> x >> y; f[x][y] = 0 ; q.push ({x, y}); } ll res = 0 ; int dx[] = {0 , 1 , 0 , -1 }, dy[] = {1 , 0 , -1 , 0 }; while (q.size ()) { auto [x, y] = q.front (); q.pop (); res += f[x][y]; for (int i = 0 ; i < 4 ; i++) { int a = x + dx[i], b = y + dy[i]; if (a < 1 || a > n || b < 1 || b > m) continue ; c[a][b]++; if (f[a][b] == -1 && c[a][b] == 2 ) { f[a][b] = f[x][y] + 1 ; q.push ({a, b}); } } } cout << res << endl; } int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int T = 1 ; while (T--) { solve (); } return 0 ; }
G. Big Banned Grid
本质是一个连通块问题,判断障碍构成的若干个连通块是否能够隔断 \((1,1)\) 和 \((H,W)\) 。
判断是否隔断的方法也很简单,如图,只需判断连通块的上下左右四个边界,和图上的四种隔断方法作比较即可。
可以使用 \(bfs\) 来构建连通块。
时间复杂度 \(O(klogn)\) 。
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #include <bits/stdc++.h> #define x first #define y second #define endl '\n' using namespace std;using ll = long long ;using PII = pair<int , int >;int read () {int x = 0 , f = 1 ;char ch = getchar ();while (ch < '0' || ch > '9' ){if (ch == '-' ) f = -1 ;ch = getchar ();}while (ch >= '0' && ch <= '9' ){x = x * 10 + ch - '0' ;ch = getchar ();}return x * f;}void print (int x) {if (x < 0 ){putchar ('-' );x = -x;}if (x > 9 ) print (x / 10 );putchar (x % 10 + '0' );}void solve () { int n, m, k; cin >> n >> m >> k; map<PII, int > p; vector<PII> s (k + 1 ) ; for (int i = 1 ; i <= k; i++) { int x, y; cin >> x >> y; s[i] = {x, y}; p[{x, y}] = i; } auto bfs = [&](int st, int ed) { queue<PII> q; q.push ({st, ed}); s[p[{st, ed}]] = {0 , 0 }; p.erase ({st, ed}); int dx[] = {0 , 1 , 0 , -1 , 1 , 1 , -1 , -1 }, dy[] = {1 , 0 , -1 , 0 , 1 , -1 , 1 , -1 }; int u = 1e9 , d = 0 , l = 1e9 , r = 0 ; while (q.size ()) { auto [x, y] = q.front (); q.pop (); u = min (u, x), d = max (d, x), l = min (l, y), r = max (r, y); for (int i = 0 ; i < 8 ; i++) { int a = x + dx[i], b = y + dy[i]; if (a < 1 || a > n || b < 1 || b > m) continue ; if (!p.count ({a, b})) continue ; s[p[{a, b}]] = {0 , 0 }; p.erase ({a, b}); q.push ({a, b}); } } if (u == 1 && l == 1 ) return false ; if (u == 1 && d == n) return false ; if (l == 1 && r == m) return false ; if (d == n && r == m) return false ; return true ; }; for (int i = 1 ; i <= k; i++) { if (s[i].x == 0 ) continue ; if (!bfs (s[i].x, s[i].y)) { cout << "No" << endl; return ; } } cout << "Yes" << endl; } int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int T = 1 ; while (T--) { solve (); } return 0 ; }