• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dwtfukgv
博客园    首页    新随笔    联系   管理    订阅  订阅
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("\n");
    }
    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("\n");
}

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;
}

 

posted on 2016-06-06 13:54  dwtfukgv  阅读(227)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3