ST表——HDU-3183

题目链接

题目含义

给出一串数以及m

要求删除m个数后,让剩下的一串数组成的整数最小

题目分析

首先,通过案例可以发现一个规律

在满足留下足够的数字的条件下, 剩下的第一个数一定是能取得的最小的数

(也可能是0)

所以我们先通过ST表找出每个区间的最小数字

然后在满足至少留有len-1个数字的情况下,在前面找出最小的数作为留下的第一个数

然后剩下的数必须在前一个数之后选,同样选能选的最小的数,最后就能得到答案了

但是如果首数字是0的话,就要限制一下输出,让首数字非0或者整数为0

题目代码

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long LL;
const int maxn=1007;
int st[maxn][10],a[maxn];
char str[maxn];
int m,n;
void ST(){
    for(int i=0;i<n;i++)
        st[i][0]=i;
    int t=log2(n);
    for(int j=1;j<=t;j++)
    for(int i=0;i+(1<<j)-1<n;i++){
        if(a[st[i][j-1]]<=a[st[i+(1<<(j-1))][j-1]])
            st[i][j]=st[i][j-1];
        else st[i][j]=st[i+(1<<(j-1))][j-1];
    }
}
int query(int l,int r){
    int len=r+1-l;
    int t=log2(len);
    if(a[st[l][t]]<=a[st[r+1-(1<<t)][t]])
        return st[l][t];
    else return st[r+1-(1<<t)][t];
}
int main(){
    while(~scanf("%s%d",&str,&m)){
        n=strlen(str);
        for(int i=0;i<n;i++)
            a[i]=str[i]-'0';
        ST();
        int len=n-m,cnt=0,l=0;
        int ans[maxn];
        for(int i=0;i<len;i++){
            ans[cnt]=query(l,n-len+i);
            l=ans[cnt++]+1;
        }
        int nn=0;
        while(a[ans[nn]]==0)nn++;
        if(nn>=cnt)printf("0\n");
        else {
            for(int i=nn;i<cnt;i++)
                printf("%d",a[ans[i]]);
            printf("\n");
        }
    }
    return 0;
}

 

posted @ 2019-08-13 20:41  helman78  阅读(218)  评论(0编辑  收藏  举报