zoukankan      html  css  js  c++  java
  • CodeForces 675C Money Transfers(贪心+奥义维护)

      题意:n个银行。 其中存款有+有-。 总和为0。 n个银行两两相邻((1,n),(1,2)...(n-1,n)); 问最少移动几次(只能相邻移动)能把所有数变为0。

      分析:思路很简单,起始答案算它为n,然后每存在一段,这段的和为0(包括就一个0的情况),这个答案就减1。如1 2 3 -6,只有一段,那么答案是4-1=3。如果是3 5 -5 -3,因为第一个和最后一个也算一段,所以共两段,答案是4-2=2。至于为什么这么做呢,因为一段的长度为len,那么从一个点出发遍历这一段需要移动len-1次(这个出发点不需要再遍历),所以每多和为0的一段,答案减1即可。

      那么我们怎么用O(n)来维护呢?不妨先看代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 
     5 int a[100000+100];
     6 
     7 int main()
     8 {
     9     int n;
    10     scanf("%d",&n);
    11     for(int i=1;i<=n;i++) scanf("%d",a+i);
    12     map<ll,int> M;
    13     ll sum = 0;
    14     int ans = 1;
    15     for(int i=1;i<=n;i++)
    16     {
    17         sum += a[i];
    18         M[sum] ++;
    19         ans = max(ans,M[sum]);
    20     }
    21     cout << n-ans << endl;
    22 }

      手动模拟一下就很好理解了,这个代码还有一个巧妙的地方在于,可以解决头尾相连的问题,如果头尾不能够移动,那么最终的答案应该是n-M[0]。具体的仔细想想就明白了,还是挺奥义的- -。

      看着这个O(n)的维护方法,突然想起之前做的某题,http://www.cnblogs.com/zzyDS/p/5650397.html

      

  • 相关阅读:
    vs报错“以下文件中的行尾不一致,是否将行尾标准化”
    redis配置
    C#中保留两位小数但不四舍五入的最优做法
    jMeter 监控cpu、内存
    project 2010 使用技巧
    JMeter2.13 连接 sql server
    JMeter2.13进行压力测试
    freefilesync 7 使用
    cmd中无法运行svn命令
    MongoDB 3 + Windows 7 X64安装及配置
  • 原文地址:https://www.cnblogs.com/zzyDS/p/5962935.html
Copyright © 2011-2022 走看看