codeforces 675C C. Money Transfers(贪心)
2016-05-19 23:24
387 查看
题目链接:
[b]C. Money Transfers[/b]
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
There are n banks in the city where Vasya lives, they are located in a circle, such that any two banks are neighbouring if their indices differ by no more than 1. Also, bank 1 and bank n are neighbours if n > 1. No bank is a neighbour of itself.
Vasya has an account in each bank. Its balance may be negative, meaning Vasya owes some money to this bank.
There is only one type of operations available: transfer some amount of money from any bank to account in any neighbouring bank. There are no restrictions on the size of the sum being transferred or balance requirements to perform this operation.
Vasya doesn't like to deal with large numbers, so he asks you to determine the minimum number of operations required to change the balance of each bank account to zero. It's guaranteed, that this is possible to achieve, that is, the total balance of Vasya in all banks is equal to zero.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of banks.
The second line contains n integers ai ( - 109 ≤ ai ≤ 109), the i-th of them is equal to the initial balance of the account in the i-th bank. It's guaranteed that the sum of all ai is equal to 0.
Output
Print the minimum number of operations required to change balance in each bank to zero.
Examples
input
output
input
output
input
output
题意:
a[i]表示这个人欠第i个银行多少钱,这个人每次只能在相邻的银行之间转账,问最少要转多少次才能使所有的a[i]的值为0;其中1和n的相邻;
思路:
可以发现,最多需要n-1次,我们可以这样想,把每个a[i]都当成一个独立的集合,围成一个圈,我们的目标是把这些集合合并成0,且操作次数最少,那么怎么才能使操作最少且有达到目标呢?那就是要尽量使集合尽量多,因为合并一个数就至少需要一次操作,一次操作就会减少一个集合,而么操作次数就是集合的减少数目,所以最后的答案就是n-最多的集合数;现在就变成了怎么找最多的集合数目了;
跟前缀和有关,这个就相当于一个区间和为0,要把这个圈的数分成最多的集合就是找前缀和出现的最多的那个次数了;
AC代码:
[b]C. Money Transfers[/b]
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
There are n banks in the city where Vasya lives, they are located in a circle, such that any two banks are neighbouring if their indices differ by no more than 1. Also, bank 1 and bank n are neighbours if n > 1. No bank is a neighbour of itself.
Vasya has an account in each bank. Its balance may be negative, meaning Vasya owes some money to this bank.
There is only one type of operations available: transfer some amount of money from any bank to account in any neighbouring bank. There are no restrictions on the size of the sum being transferred or balance requirements to perform this operation.
Vasya doesn't like to deal with large numbers, so he asks you to determine the minimum number of operations required to change the balance of each bank account to zero. It's guaranteed, that this is possible to achieve, that is, the total balance of Vasya in all banks is equal to zero.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of banks.
The second line contains n integers ai ( - 109 ≤ ai ≤ 109), the i-th of them is equal to the initial balance of the account in the i-th bank. It's guaranteed that the sum of all ai is equal to 0.
Output
Print the minimum number of operations required to change balance in each bank to zero.
Examples
input
3 5 0 -5
output
1
input
4 -1 0 1 0
output
2
input
4 1 2 3 -6
output
3
题意:
a[i]表示这个人欠第i个银行多少钱,这个人每次只能在相邻的银行之间转账,问最少要转多少次才能使所有的a[i]的值为0;其中1和n的相邻;
思路:
可以发现,最多需要n-1次,我们可以这样想,把每个a[i]都当成一个独立的集合,围成一个圈,我们的目标是把这些集合合并成0,且操作次数最少,那么怎么才能使操作最少且有达到目标呢?那就是要尽量使集合尽量多,因为合并一个数就至少需要一次操作,一次操作就会减少一个集合,而么操作次数就是集合的减少数目,所以最后的答案就是n-最多的集合数;现在就变成了怎么找最多的集合数目了;
跟前缀和有关,这个就相当于一个区间和为0,要把这个圈的数分成最多的集合就是找前缀和出现的最多的那个次数了;
AC代码:
#include <bits/stdc++.h> using namespace std; #define Riep(n) for(int i=1;i<=n;i++) #define Riop(n) for(int i=0;i<n;i++) #define Rjep(n) for(int j=1;j<=n;j++) #define Rjop(n) for(int j=0;j<n;j++) #define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; const LL mod=1e9+7; const double PI=acos(-1.0); const int inf=0x3f3f3f3f; const int N=1e5+25; int n,a ; LL sum ; map<LL,int>mp; int main() { scanf("%d",&n); int ans=0; Riep(n) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; mp[sum[i]]++; ans=max(ans,mp[sum[i]]); } cout<<n-ans<<"\n"; return 0; }
相关文章推荐
- 基于bootstrap 的确认框
- JavaScript跨域(1):什么是跨域,如何跨域
- 关于JSP的思考
- js事件、事件委托
- 做 h5 推荐几个东西吧
- css中的baseline
- Asynchronous JavaScript And XML (Ajax)由浅入深
- 使用WebRTC搭建前端视频聊天室——入门篇
- JS中的文档碎片
- JSON和XML区别和优缺点比较
- jsp的静态引入与动态引入的异同点
- Codeforces--675C--Money Transfers(思维)
- 关于bootstrap的日历控件daterangepicker
- NodeJS学习笔记 - Express4.x路由操作
- JavaScript学习(一)---DOM操作
- css3加js做一个简单的3D行星运转效果
- CSS选择器
- 剑指Offer 二进制中的1的个数
- LeetCode-237.Delete Node in a Linked List
- 前端性能优化小知识点(javascript)