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
  • 相关阅读:
    SpringMVC-11-文件上传和下载
    SpringMVC-10-拦截器Interceptor
    SpringMVC-09-Ajax技术
    SpringMVC-08-整合SSM之CRUD
    SpringMVC-08-SpringMVC层编写
    SpringMVC-08-整合SSM之Spring层编写
    SpringMVC-08-Mybatis层编写
    SpringMVC-08-整合SSM之基本环境搭建
    SpringMVC-07-JSON讲解
    SpringMVC-06-数据处理
  • 原文地址:https://www.cnblogs.com/BearChild/p/7756059.html
Copyright © 2011-2022 走看看