• 暑假集训Day4 B(贪心好题+二分答案)


    题目链接在本地,题目大意是从一段只包含0,1,2 的字符串中选出若干个子序列“2020”,选出一个2020序列以后,这四个数字从原来的位置上删除,问最多能选出多少个这种序列。

    一开始想的贪心思想是从左往右扫描,越靠左满足2020的越先选出来,后来发现了反例就是20202200,如果越靠左满足的越先选出来,那这个只能选出一个2020,但是我们可以先选左边的20,然后在后四个中取出一个20,另一个同理,因此这种贪心思想是错误的。

    我们现在考虑另一种贪心思想,对于出现的2和0,我们一定把它当做第一个2和0,为什么这么做可以参考上面的反例。但是这个新的20不能全当新的,一定是到了一个数目为止,后面出现的20都作为第二个20,现在我们需要知道这个数是多少,这个步骤用二分做即可。

    这题主要难想的是贪心的思想,一定要先满足前面的够用才能统计后面的20,不然就会出现反例中的情况。

     1 #include "bits/stdc++.h"
     2 using namespace std;
     3 const int MAX=1e5+5;
     4 int n,a[5];
     5 char s[MAX];
     6 bool feasible(int x){
     7     int i,j;
     8     a[1]=a[2]=a[3]=a[4]=0;
     9     for (i=1;i<=n;i++){
    10         if (s[i]=='2'){
    11             if (a[1]!=x) a[1]++;
    12             else if (a[3]<a[2]) a[3]++;
    13         }
    14         if (s[i]=='0'){
    15             if (a[2]!=x){
    16                 if (a[2]<a[1]) a[2]++;
    17             }
    18             else{
    19                 if (a[4]<a[3]) a[4]++;
    20             }
    21         }
    22         if (a[4]==x) return true;
    23     }
    24     return false;
    25 }
    26                 
    27 int main(){
    28 //    freopen ("b.in","r",stdin);
    29 //    freopen ("b.out","w",stdout);
    30     int i,j,low,high,mid,ans;
    31     while (scanf("%d",&n)!=EOF){
    32         scanf("\n%s",s+1);
    33         low=1,high=n;
    34         ans=0;
    35         while (low<=high){
    36             mid=(low+high)>>1;
    37             if (feasible(mid)){
    38                 ans=mid;
    39                 low=mid+1;
    40             }
    41             else high=mid-1;
    42         }
    43         printf("%d\n",ans);
    44     }
    45     return 0;
    46 }
  • 相关阅读:
    java ,js获取web工程路径
    js 无刷新分页代码
    js 获取时间对象代码
    jquery 文本框失去焦点显示提示信息&&单击置空文本框
    CodeForces
    nth_element() O(n)复杂度求第k+1小元素
    CodeForces
    HDU
    杜教BM
    J
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/16456107.html
Copyright © 2020-2023  润新知