1 条题解
-
1
做法一(暴力 DFS)
由于 n ≤ 10,可以直接用 DFS 枚举每天是“工具校准”还是“工具保养”。
时间复杂度:O(2ⁿ) 期望得分:10 分
做法二(贪心枚举)
假设校准天数固定为 k。 我们可以认为前 k 天全为“工具校准”,从而得到熟练度序列:
x, 2x, 3x, ..., kx, (k−1)x, ..., 2x, x
共 2k − 1 个熟练度。
将这些熟练度降序排序,然后使用双指针贪心匹配文物难度 Dᵢ。
时间复杂度:O(n²) 期望得分:60 分
做法三(二分最优天数)
继续分析发现:校准天数单调递增有利于修复更多文物。
因此可对校准天数进行二分搜索,check() 时使用做法二判断是否可行。
关于二分上界:熟练度形成“金字塔”形状,为了能覆盖所有 Dᵢ, 上界可取 1e5 + 1e5/2 + 10。
时间复杂度:O(n log x) 期望得分:100 分
#include<bits/stdc++.h> using namespace std; #define ll long long const int N = 1e5+5; ll n, x, a[N]; bool cmp(int a, int b) { return a > b; } bool check(int d) { // i 用来表示这个三角形的从上到下的数, j 枚举 文物数列, o用于做 三角形的两侧 for (ll i = d * x, j = 1, o = 1; i >= 0 && j <= n; i -= o*x, j++, o ^= 1) //注意这里的 o一定要初值为1,顶点一个 if (i < a[j]) return false; return true; } void slove() { cin >> n >> x; for (int i = 1; i <= n; i++) cin >> a[i]; sort(a + 1, a + 1 + n, cmp); ll l = 0, r = 1e8, ans = 0; while (l <= r) { int mid = (l + r) >> 1; if (check(mid)) ans = mid, r = mid - 1; else l = mid + 1; //cout << l << " " << r << " " << ans << endl; } cout << ans; } int main() { freopen("fix.in","r",stdin); freopen("fix.out","w",stdout); int _ = 1; //cin >> _; while (_--) { slove(); } return 0; }
- 1
信息
- ID
- 12
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 2
- 标签
- 递交数
- 274
- 已通过
- 14
- 上传者