• Uva 11491 Erasing and Winning


    Thinking about it:

      题目要求是删除D个数,因为总共有N个数,因此也可以看作在N个数中选择d = N - D个数。

      怎么选呢?选择第一个数时,肯定是在[ 0, N - D ] 的位置上选,既然选,肯定在这区间内选最大的。如果最大值有多个,那么选位置靠前的,因为这样可以选第一个数的最大值可能用于第二个数。假设,第一个数选的位置为p, 那么第二个数则在[ p+1, N - D + 1 ]的位置选,以此类推,直至全部选完。

      因为是在一个区间内选取最大值,所以在选最大值上可以做一些预处理:计算每个位置 i, 离 i 两边最近,且比 i 所在位置值要大的位置。比如 13215,i = 2 时,比 2 大的值,左边最近的在1, 右边最近的在4。知道这两个值,就可以快速判断 2 在区间 [ 1 ,3 ] ,[ 2, 3 ]上是不是最大的了。

    Refefence:

      1. 《算法竞赛入门经典(第2版)》

      2. http://blog.csdn.net/u014800748/article/details/43671343

    PS:

      这题的解决方法有很多,我在AC后看了他人的题解,每个人的实现方法都有所差异,有些方法值得学习。

    Code:

    /**
     * AC @ Sep 8th 2015
     * Run Time : 0.049s
     */
    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 10e5 + 50;
    int N, D;
    int l[MAXN], r[MAXN];
    // l[i]; the nearest pos bigger than digits[i] on the left
    // r[i]; the nearest pos bigger than digits[i] on the right
    string digits;
    std::vector<int> ans;
    
    void init() {
        int hash[15]; // right
        for (int i = 0; i < 15; ++i) {
            hash[i] = MAXN;
        }
        for (int i = N-1; i >= 0; --i) {
            int tmp = MAXN;
            for (int j = digits[i]- '0' + 1; j < 10; ++j) {
                tmp = min(hash[j], tmp);
            }
            hash[digits[i]- '0'] = i;
            r[i] = tmp;
        }
        memset(hash, -1, sizeof(hash)); // left
        for (int i = 0; i < N; ++i) {
            int tmp = -1;
            for (int j = digits[i]-'0' + 1; j < 10; ++j) {
                tmp = max(hash[j], tmp);
            }
            hash[digits[i]- '0'] = i;
            l[i] = tmp;
        }
    }
    
    void find(int start, int d) {
        if (!d) {
            return ;
        }
        int i;
        for(i = start; i <= N - d; ++ i) {
            if (l[i] < start && r[i] > N-d) {
                break;
            }
        }
        ans.push_back(digits[i]-'0');
        find(i+1, d-1);
    }
    
    void work() {
        init();
        ans.clear();
        find(0, N-D);
        for (std::vector<int>::iterator it = ans.begin(); it != ans.end(); ++it) {
            cout << *it;
        }
        cout << endl;
    }
    
    int main(int argc, char const *argv[]) {
        ios::sync_with_stdio(false);
        cin.tie(0);
        while(cin >> N >> D && (N + D)) {
            cin >> digits;
            work();
        }
        return 0;
    }
    

      

  • 相关阅读:
    saltstack配置详解
    前端html&Css快速入门...
    pymysql实现注册登录
    Mysql学习入门到放弃ing...
    python学习之选课系统项目(面向对象)
    python 面向对象和类
    python开发三层架构
    python 查看某个文件下最新更新的日期文件
    python写小说阅读功能~
    删除链表中重复的结点
  • 原文地址:https://www.cnblogs.com/Emerald/p/4791221.html
Copyright © 2020-2023  润新知