[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;
}