zoukankan      html  css  js  c++  java
  • 【Foreign】减法 [二分][贪心]

    减法

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

      给你一个n个数的序列A,并且给出m次操作B。

      操作的含义是:每次从A中选出不同的B_i个数,把它们减去1。一个数>0被看作是可以选择的。

      问最多执行完第几个操作。

    Input

      第一行给出两个整数,序列长度n与操作数m。

      第二行n个数,表示序列A。

      第三行m个数,表示操作序列B。

    Output

      输出一个整数,表示最多执行完第几个操作。

    Sample Input

      3 4
      2 1 3
      3 1 2 1

    Sample Output

      3

    HINT

      1 <= n, m <=100000

    Solution

      考虑贪心,显然是每次减去大的数

      我们二分答案做到第几次,然后构造一组不上升序列times,表示每个数最多可以被减几次,每次把区间[1, B[i]]加一。

      如果每个数都足够大的话,这显然是一组合法解。但是每个数不一定都够减

      我们可以基于这个序列来做调整,考虑什么情况下是合法的呢?
      显然,前面不够减的可以是分摊到后面去,而若A从大到小排序,贪心尽量多减,那么后面减的次数不可能比前面多,所以这样就保证了合法性

      所以先把A从大到小排序然后O(n)递推。

      每次 left += times[i] - A[i]
        如果left<=0,表示这个位置的值减完还有剩余,但是这个left不能分摊给后面用,所以我们把left设为0
        如果left>0,可以把left留在后面减,传递下去即可。

      递推完只要判断一下最后是否left<=0

    Code

     1 #include<iostream>
     2 #include<string>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cmath>
     8 using namespace std;
     9 typedef long long s64;
    10 
    11 const int ONE = 1000005;
    12 const int MOD = 1e9 + 7;
    13 
    14 int n, m;
    15 int A[ONE], B[ONE];
    16 int times[ONE];
    17 bool cmp(int a, int b) {return a > b;}
    18 
    19 int get()
    20 {
    21         int res=1,Q=1;  char c;
    22         while( (c=getchar())<48 || c>57)
    23         if(c=='-')Q=-1;
    24         if(Q) res=c-48; 
    25         while((c=getchar())>=48 && c<=57) 
    26         res=res*10+c-48;
    27         return res*Q; 
    28 }
    29 
    30 int Check(int mid)
    31 {
    32         for(int i = 1; i <= n; i++) times[i] = 0;
    33         for(int i = 1; i <= mid; i++)
    34         {
    35             times[1]++, times[B[i] + 1]--;
    36             if(B[i] > n) return 0;
    37         }
    38         
    39         int left = 0;
    40         for(int i = 1; i <= n; i++)
    41         {
    42             times[i] += times[i - 1];
    43             left += times[i] - A[i];
    44             if(left <= 0) left = 0;
    45         }
    46         
    47         return left <= 0;
    48 }
    49 
    50 int main()
    51 {
    52         n = get();    m = get();
    53         for(int i = 1; i <= n; i++) A[i] = get();
    54         for(int i = 1; i <= m; i++) B[i] = get();
    55         sort(A + 1, A + n + 1, cmp);
    56         
    57         int l = 0, r = m;
    58         while(l < r - 1)
    59         {
    60             int mid = l + r >> 1;
    61             if(Check(mid)) l = mid;
    62             else r = mid; 
    63         }
    64         
    65         if(Check(r)) printf("%d", r);
    66         else printf("%d", l);
    67 }
    View Code
  • 相关阅读:
    根据不同的窗口尺寸来选择不同的样式
    用JavaScript检测视频格式支持
    用JavaScript检测音频格式支持
    C#取整函数Math.Round、Math.Ceiling和Math.Floor
    asp.net在同一页面跳转到指定位置
    对存储过程进行加密和解密
    各种SQL语句
    centos7.2安装nginx
    springboot利用mock进行junit单元测试,测试controller
    centos7环境搭建一台mysql服务器启动多个端口
  • 原文地址:https://www.cnblogs.com/BearChild/p/7756059.html
Copyright © 2011-2022 走看看