[CF675C] Money Transfer

[CF675C] Money Transfer - 思维

Description

给你 n 个银行中的存款(负值表示借贷),是成环的,1 跟 n 相接,这 n 个数的和为 0。可以从 i 向 i 的相邻两侧转移存款,问你最少转移多少次,可以让所有银行的存款都为 0。

Solution

如果没有成环的条件,那么我们处理出前缀和序列 s,则所有 s=0 的位置右边可以作为一个分割点,每个分割点内单独处理,答案即为 n-分割点个数。

考虑到有成环的条件,相当于我们可以选取任意一个 s[i] 作为零点,于是问题也就转化为求前缀和序列中出现最多的数出现的次数。

#include <bits/stdc++.h>
using namespace std;

#define int long long

signed main()
{
    ios::sync_with_stdio(false);

    int n;
    cin >> n;

    vector<int> a(n + 2), s(n + 2);

    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        s[i] = s[i - 1] + a[i];

    map<int, int> mp;
    for (int i = 1; i <= n; i++)
        mp[s[i]]++;

    int ans = 0;
    for (auto pr : mp)
        ans = max(ans, pr.second);

    cout << n - ans << endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/14346069.html