AcWing第9場周賽題解
阿新 • • 發佈:2022-04-09
A. 3778. 平衡陣列
題目連結:https://www.acwing.com/problem/content/3781/
題目大意:\(m\) 次題目要求的操作使最終所有數都相等。
解題思路:思維題。將所有元素加上 \(i\) 等價於將這個數減去 \(i\)。所以一種必定可行的方案就是一次操作第 \(2, 3, \ldots, n\)。
示例程式:
#include <bits/stdc++.h> using namespace std; int T, n; int main() { cin >> T; while (T--) { cin >> n; cout << n-1 << endl; for (int i = 2; i <= n; i++) { if (i > 2) cout << " "; cout << i; } cout << endl; } return 0; }
B. 3779. 相等的和
題目連結:https://www.acwing.com/problem/content/3782/
題目大意:略。
解題思路:列舉。先求出每個序列的和,設第 \(i\) 個數列的元素和為 \(sum_i\),然後對於 第 \(i\) 個數列中的數值為 \(x\) 的元素,刪除 \(x\) 後數列中剩餘元素和為 \(sum_i - x\),判斷 \(sum_i - x\) 在別的數列中是否存在(用 map),如果如在一個 \(sum_j - y = sum_i - x\),則答案就找到了。
示例程式:
#include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 5; int k, n, a[maxn]; map<int, pair<int, int>> mp; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> k; for (int i = 1; i <= k; i++) { cin >> n; int sum = 0; for (int j = 1; j <= n; j++) { cin >> a[j]; sum += a[j]; } for (int j = 1; j <= n; j++) { if (mp.find(sum - a[j]) != mp.end()) { pair<int, int> v = mp[sum - a[j]]; if (v.first != i) { cout << "YES" << endl; cout << v.first << " " << v.second << endl; cout << i << " " << j << endl; return 0; } } else mp[sum - a[j]] = {i, j}; } } cout << "NO" << endl; return 0; }
題目大意:
解題思路:(下面說的遞增/遞減指的都是非嚴格單調遞增/遞減)
考慮到最終的數列只有如下三種情況:
- 全部遞增;
- 全部遞減;
- 先遞增再遞減。
所以可以定義狀態 \(f_{1,i}\) 表示區間 \([1,i]\) 遞增的情況下的最大和,\(f_{2,i}\) 表示區間 \([i,n]\) 遞減的情況下的最大和,則答案為 \(\max\{ f_{1,i} + f_{2,i+1} \}\)
實現時可以使用 單調佇列 優化。
示例程式:
#include <bits/stdc++.h> using namespace std; const int maxn = 5e5 + 5; int n; long long a[maxn], f1[maxn], f2[maxn]; deque<int> que; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; // 先從前往後求 f1[i] for (int i = 1; i <= n; i++) { while (!que.empty() && a[que.back()] > a[i]) que.pop_back(); int p = que.empty() ? 0 : que.back(); f1[i] = f1[p] + (i - p) * a[i]; que.push_back(i); } // 再從後往前求 f2[i] que.clear(); for (int i = n; i >= 1; i--) { while (!que.empty() && a[que.back()] > a[i]) que.pop_back(); int p = que.empty() ? (n+1) : que.back(); f2[i] = f2[p] + (p - i) * a[i]; que.push_back(i); } int x = 1; // 最大值下標 for (int i = 2; i <= n; i++) if (f1[i] + f2[i] - a[i] > f1[x] + f2[x] - a[x]) x = i; long long y = a[x]; for (int i = x-1; i >= 1; i--) y = a[i] = min(y, a[i]); y = a[x]; for (int i = x+1; i <= n; i++) y = a[i] = min(y, a[i]); for (int i = 1; i <= n; i++) { if (i > 1) cout << " "; cout << a[i]; } cout << endl; return 0; }