A Magic Lamp(HDU3183)

换OJ祭

上面是题目链接。
这道题怎么做呢?
我们的思路是一个一个确定
因为我们并不能改变顺序
而且我们知道,对一个数大小影响最大的,是第一个数字
其次是第二个数字,依次往后
所以我们要尽可能是高位的数字变小
所以我们也是由高位到低位确定
如何确定呢?
我们举个例子,比如我又一个长度为10的数字,我可以删除3个数字
那么我的ans一定是长度为7的数
那么我的第一位只能在前4位当中选
因为你至少要给后面留6位
所以我们就有了一个1到4的范围,然后求出这个范围中的最小的数字,把它放入ans即可,然后继续。
我们这里解题时,ST表我们不保存我们的数字,我们保存最小数字的下标
这步操作只需要我们加一个创新的min函数即可。
代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
int m,n;
char a[1005];
char num[1005];
int f[1005][1005];
int min(int i,int j){
    return a[i]<=a[j] ? i:j;
}
void ST(){
    int i,j;
    for(i=0;i<n;i++){
        f[i][0]=i;
    }

    for(j=1;j<=(int)(log((double)n)/log(2.0));j++){
        for(i=0;i+(1<<j)-1<n;i++){
            f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }

    }
}
int query(int L,int R){
    int x=(int)(log(double(R-L+1))/log(2.0));
    return min(f[L][x],f[R-(1<<x)+1][x]);
}
int main(){
    int i,j,L,R;
    while(~scanf("%s%d",a,&m)){
        int len=strlen(a);
        n=len;
        m=len-m;
        ST();
        i=j=0;
        while(m--){
            i=query(i,len-m-1);
            num[j++]=a[i++];
        }
        for(i=0;i<j;i++){
            if(num[i]!='0'){
                break;
            }
        }
        if(i==j){
            printf("0\n");
            continue;
        }
        while(i<j){
            printf("%c",num[i]);
            i++;
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cggwz/article/details/81106937