B. The Walkway - 思维

B. The Walkway - 思维_第1张图片

 B. The Walkway - 思维_第2张图片

 B. The Walkway - 思维_第3张图片

 分析:

        补题, 首先大体思路就是先算一遍没改变任何点时能够买到的物品,这一步可以通过看两点之间距离,之间能够包含几个d就说明会需要买几次物品,对于两侧边界,可以将左侧设置为1 - d, 因为此时可以计算第一个到1之间需不需要买,最后一个数设置为n + 1,就可以计算最后一个点到离开之间需不需要买,可以认为找的两点之间的距离是包括前一个点不包括后一个点的,这样每次只会处理一个点。然后枚举每一个点,判断移动这个点会产生什么影响,a = (s[i] - s[i - 1] - 1) / d也就是这个点到前一个点的距离之间需要买几次,b = (s[i + 1] - s[i] - 1) / d是这个点的后一个点到这个点的距离之间需要买几次,c = (s[i + 1] - s[i - 1] - 1) / d是不看这个点看两侧的点之间需要买几次,也就是移动这个点后的买的次数,用c - (a + b)就可以得到移动当前的点会产生的变化差值,然后总的买的次数还需要加上剩余的m - 1个点,对每一个得到的答案都取最小值,在找到有多少个最小值,就可以得出答案。

代码:

#include 

using namespace std;
using ll = long long;

typedef pair pii;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    while(T --) {
        ll n, d;
        int m;
        cin >> n >> m >> d;
        vector s(m + 2);
        s[0] = 1 - d;
        s[m + 1] = n + 1;
        for(int i = 1; i <= m; i ++) cin >> s[i];
        int sum = 0;
        for(int i = 1; i <= m + 1; i ++) {
            sum += (s[i] - s[i - 1] - 1) / d;
        }
        int ans = n + 1;
        int cnt = 0;
        for(int i = 1; i <= m; i ++) {
            int t = sum;
            int a = (s[i] - s[i - 1] - 1) / d;
            int b = (s[i + 1] - s[i] - 1) / d;
            int c = (s[i + 1] - s[i - 1] - 1) / d;
            t += (c - (a + b));
            t += (m - 1);
            if(ans > t) {
                ans = t;
                cnt = 1;
            }
            else if(ans == t) cnt ++;
        }
        cout << ans << ' ' << cnt << '\n';
    }
}

你可能感兴趣的:(c++,算法,思维)