• UVa 11491 Erasing and Winning (贪心,单调队列或暴力)


    题意:给一个数字(开头非0),拿掉其中的d个数字,使剩下的数字最大(前后顺序不能变)。

    析:拿掉d个数字,还剩下n-d个数字。相当于从n个数字中按先后顺序选出n-d个数字使组成的数字最大,当然采用窗口滑动优先选取大的。

    也就是说,当然第一位最大,这个数就最大了,所以这是一个贪心算法。我开始并不知道有这个算法,

    所以开始我是暴力的,700ms,要是数据量再大一点,就TLE了。所以我想肯定有高效率的算法,查了查,原来还有这个。

    先说我想法,首先在前d个数字中选最大的,然后在从这个数字到d+1个中选最大的,依次往后,贪心。

    想法很简单,就是太慢了。然后我再说单调队列,就是用一个队列,里面是从大到小排的,必须是这样的,先对前d-1个进行预处理,

    把太小的都删了,然后一个一个的放,放的时候把小于该值的都删了,保证是从大到小的,每次从队首取元素,保证是最大的。

    如果还觉得太慢了,可以在删除元素时用二分查找,更快的确定位置。

    代码如下:

    暴力代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    const int maxn = 100000 + 10;
    int a[maxn];
    char s[maxn];
    
    int main(){
    //    freopen("in.txt", "r", stdin);
        int n, d;
        while(scanf("%d %d", &n, &d) == 2 && n){
            scanf("%s", s);
            for(int i = 0; i < n; ++i)  a[i] = s[i] - '0';
    
            int indx = 0;
            int st = 0, ed = d+1;
            while(true){
                int m = -1;
                for(int i = st; i < ed; ++i){
                    if(a[i] > m){ m = a[i];  st = i + 1; }
                    if(9 == m)  break;
                }
                printf("%d", m);
                if(ed == n)  break;
                ++ed;
            }
    
            printf("
    ");
        }
        return 0;
    }
    

    单调队列代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    const int maxn = 100000 + 10;
    struct node{
        int id, val;
    };
    char s[maxn];
    node a[maxn], q[maxn];
    
    void solve(int k, int n){
        int front = 0, rear = -1;
        for(int i = 0; i < k; ++i){
            while(front <= rear && q[rear].val < a[i].val)  --rear;//预处理前d个,要保证是单调的,小于的都删掉
            q[++rear] = a[i];
        }
    
        int id = -1;
        for(int i = k; i < n; ++i){
            while(front <= rear && q[rear].val < a[i].val)  --rear;//同上
            q[++rear] = a[i];
    
            while(q[front].id <= id)  ++front;//因为是有顺序的,要往后放
            printf("%d", q[front].val);
            id = q[front].id;
        }
        printf("
    ");
    }
    
    int main(){
    //    freopen("in.txt", "r", stdin);
        int n, d;
        while(scanf("%d %d", &n, &d) == 2 && n){
            scanf("%s", s);
            for(int i = 0; i < n; ++i){
                a[i].id = i;
                a[i].val = s[i] - '0';
            }
    
            solve(d, n);
        }
        return 0;
    }
    
  • 相关阅读:
    除下草并推荐PhantomJS
    GTAC 2013
    Benchmark感受
    ChinaTest第二天
    "西厂"、"东厂"照片
    谈面试上
    mysql基本常用命令(转)
    java学习笔记数据类型、运算符和控制语句
    java学习笔记第一个applet程序以及一个小问题的解决
    网上阅卷系统自动识别功能代码
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5563615.html
Copyright © 2020-2023  润新知