• HDU 3183


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183

    Problem Description
    Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams.
    The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
    You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?

    Input
    There are several test cases.
    Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.

    Output
    For each case, output the minimum result you can get in one line.
    If the result contains leading zero, ignore it.

    Sample Input
    178543 4
    1000001 1
    100001 2
    12345 2
    54321 2

    Sample Output
    13
    1
    0
    123
    321

    题意:

    给你一个 $n$ 位的数字,你要删除其中的 $m$ 位,使得剩下来的每一位组成一个新数字是最小的。

    题解:

    换句话说,就是要在 $n$ 位中选择 $k=n-m$ 位数字组成新数字,使其最小。

    显然,新数字的最高位必须在 $[1,n-k+1]$ 内,否则后面的数字将不够用。因此我们可以按照贪心的策略在 $[1,n-k+1]$ 内寻找最小的数字作为最高位。

    然后,就转变为一个子问题:去掉选定的最高位,以及其前面的所有数字,剩下来的一串数字里,寻找 $k-1$ 位数字组成最小新数字。

    一般来说,线段树是区间查询最大值的一种非常优秀的解决方法。不过本题没有修改操作,用线段树比较浪费。本题适合使用解决RMQ问题的著名的ST算法。

    ST算法是基于倍增思想的。对于一个给定的序列 $a[1 sim n]$,它能够在 $O(n log n)$ 的预处理后,以 $O(1)$ 的时间复杂度在线地给出任意区间的最值。

    首先我们知道,对于序列 $a[1 sim n]$,它的子区间数目是 $O(n^2)$ 的。根据倍增思想,我们在这 $O(n^2)$ 的状态空间内选择一些 $2$ 的整数次幂的位置作为关键位置。

    假设 $f(i,j)$ 代表了区间 $[i,i+2^j-1]$ 的最大值,即以 $a[i]$ 为起始的 $2^j$ 个数的最大值。显然递推边界为:对于任意的 $i in [1,n]$,有$f(i,0) = a[i]$。

    接下来,在递推求 $f(i,j)$ 时,区间的长度是成倍增长的,即 $f(i,j) = max[f(i,j-1),f(i+2^{j-1},j-1)]$。从这个递推式不难看出,只要我们从小到大枚举 $j$,且对于固定的 $j$ 枚举 $i$ 即可。

    而当我们要求 $[l,r]$ 的最大值时,我们可以求得 $k = log(r-l+1)$,显然从 $l$ 往后的 $2^k$ 个数和从$r$ 往前的 $2^k$ 个数能够完全覆盖 $[l,r]$,因此只需要返回 $f(l,k)$ 和 $f(r-2^k+1,k)$ 中的较大值即可。

    以下为求解RMQ问题的ST算法模板:

    namespace ST
    {
        int n;
        int f[maxn][(int)log2(maxn)+5];
        void init(int _n,int* a)
        {
            n=_n;
            for(int i=1;i<=n;i++) f[i][0]=a[i];
            for(int j=1;(1<<j)<=n;j++)
                for(int i=1;i<=n-(1<<j)+1;i++)
                    f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
        int query(int l,int r)
        {
            int k=log2(r-l+1);
            return max(f[l][k],f[r-(1<<k)+1][k]);
        }
    }

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    const int maxn=1005;
    
    int n,m,k;
    char num[maxn];
    queue<int> q;
    
    namespace ST
    {
        int n;
        pii f[maxn][(int)log2(maxn)+5]; //first存储最小值,second存储最小值位置
        pii min(const pii& a,const pii& b)
        {
            if(a.first==b.first)
                return a.second<b.second?a:b;
            else
                return a.first<b.first?a:b;
        }
        void init(int _n,char* a)
        {
            n=_n;
            for(int i=1;i<=n;i++) f[i][0]=make_pair(a[i]-'0',i);
            for(int j=1;(1<<j)<=n;j++)
                for(int i=1;i<=n-(1<<j)+1;i++)
                    f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
        pii query(int l,int r)
        {
            int k=log2(r-l+1);
            return min(f[l][k],f[r-(1<<k)+1][k]);
        }
    }
    
    void solve(queue<int>& q,int l,int r,int k)
    {
        if(k==0) return;
        pii x=ST::query(l,r-k+1);
        q.push(x.first);
        solve(q,x.second+1,r,k-1);
    }
    int main()
    {
        while(scanf("%s%d",num+1,&m)!=EOF)
        {
            n=strlen(num+1), k=n-m;
            ST::init(n,num);
            solve(q,1,n,k);
            while(!q.empty())
            {
                if(q.front()==0) q.pop();
                else break;
            }
            if(q.empty()) q.push(0);
            while(!q.empty())
            {
                printf("%d",q.front());
                q.pop();
            }
            printf("
    ");
        }
    }
  • 相关阅读:
    Setting a maximum attachment size
    一机多屏,屏幕顺序容易错?
    node.js " The requested service provider could not be loaded or initialized"
    VS2008中MFC对话框界面编程Caption中文乱码的解决办法
    The application was unable to start correctly (0xc000007b)
    FreeType的项目总是报error LNK2019: unresolved external symbol __imp错误
    MFC对话框:模态对话框及其弹出过程
    MFC如何获取硬盘的序列号
    SharePoint CAML Query小结
    ECS Navicat for MySQL远程连接报10038的错误
  • 原文地址:https://www.cnblogs.com/dilthey/p/6804133.html
Copyright © 2020-2023  润新知