CF1623C Balanced Stone Heaps

CF1623C

原题链接←Click it

题目大意:有\(i(i >= 3)\)堆石子,每堆石子的个数为\(h_i\),现在从第\(3\)堆到第\(n\)堆石子进行操作,每次都可以选择\(d\)个石头,使得\(h_{i - 2} += 2 * d\)\(h_{i_1} += d\)\(h_i -= 3 * d\)。求操作完成之后数量最少的堆中石子可能的最大值。

解题思路:显然是一个二分查找,但是check函数在写的过程中有些波折。刚开始的时候我是选择从顺序模拟,但是发现对第\(i\)堆石子操作的时候,发现如果第\(i - 2\)堆石子满足条件,但是第\(i - 1\)堆石子不满足条件的情况下,我们就必须要考虑第\(i + 1\)堆石子对\(i - 1\)堆的贡献。也就是说从顺序模拟需要考虑之后的不确定因素,但是逆序模拟的时候,可以贪心地让第\(i\)堆石子剩下可能的最小值,因为前面的堆无法影响到后面的堆,因此理论上我们对第\(i\)堆石子每次可移动的\(d =\lfloor \frac{nh[i] - m}{3} \rfloor\),但是实际上在顺序模拟的过程中发现每堆石子可移动的\(d <= \lfloor \frac{h[i]}{3}\rfloor\),因此我们可以贪心地取\(d = min(\lfloor \frac{nh[i] - m}{3} \rfloor,\lfloor \frac{h[i]}{3}\rfloor)\),并检查每个\(nh[i]\)是否大于\(m\)

参考代码:

vector<int> h;
bool check(int m) {
    vector<int> nh = h;
    for(int i = nh.size() - 1; i >= 2; i --) {
        if(nh[i] < m) return 0;
        int d = min(h[i], nh[i] - m) / 3;
        nh[i - 1] += d;
        nh[i - 2] += 2 * d;
    }
    return b[0] >= m && b[1] >= m;
}
void solve() {
    int n;
    cin >> n;
    a.resize(n);
    int l = INF, r = INF;

    for(int i = 0; i < n;i ++) {
        cin >> a[i];
        l = min(l, a[i]);
    }
    while(l < r) {
        int m = l + r + 1 >> 1;
        if(check(m)) l = m;
        else r = m - 1;
    }
    cout << l << '\n';
}
posted @ 2022-03-25 19:34  Muly  阅读(43)  评论(0)    收藏  举报