1 条题解

  • 1
    @ 2025-12-31 23:59:04

    做法一(暴力 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
    上传者