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 2Sample Output
13 1 0 123 321对于一个n位数,删除m个位后,得到的最小数是什么,比如12345 2,删除两个位,得到最小的就是123.。模拟了半天复杂度也是没超过各种细节也处理了就是一直wa,然后一直没想到是RMQ,
具体就是我们要删除m个数,令res=n-m,这样就变成了要取res个数,问题就变成了从n个数中取res个数,使得组合成的数字最小,且从左到右,那么我们要怎么取呢?下面举例说明:比如54321这组数据,我们要取3个数字使得组合成的数字最小,那么第一个数取的最大范围就是在543中取(从第一个位置开始取),因为要保证至少是个三位数,所以至少要留两位,我们取得3,接下来就是从3这个位置取 取2个数字且保证这两个数字组合成的两位数最小,同样的,我们至少要留一位,所以取2,就这样重复同样的过程,用一个循环就能解决了,当然还要注意的是,我们需要得到这个数的位置,比如我们第一次取3之后,我们从哪开始取呢?这就需要3这个数所在的位置了,我们在ST表算法中用dp[i][j]记录的是位置,比较的是此位置的字符大小!
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<map>
#include<iomanip>
#include<math.h>
using namespace std;
typedef long long ll;
typedef double ld;
const int INF = 0x3f3f3f3f;
int dp[1005][50];
using namespace std;
int n;
char str[1005];
void init()
{
memset(dp, INF, sizeof dp );
for (int i=0; i<n; i++)
dp[i][0]=i;
for (int j=1; (1<<j)<=n; j++)
{
for(int i=0; i+(1<<j)-1<n; i++)
{
if(str[dp[i][j-1]]<=str[dp[i+(1<<(j-1))][j-1]])
dp[i][j]=dp[i][j-1];
else
dp[i][j]=dp[i+(1<<(j-1))][j-1];
}
}
}
int rmq(int l, int r)
{
int k=(int)(log2(r-l+1));
if(str[dp[l][k]]<=str[dp[r-(1<<k)+1][k]])
return dp[l][k];
else
return dp[r-(1<<k)+1][k];
}
int main()
{
while(~scanf("%s",str))
{
n=strlen(str);
init();
int m;
scanf("%d",&m);
if(m>=n)
{
printf("0\n");
continue;
}
int res=n-m;
int ans[1005];
int cnt=0;
int l=0;
int r=n-res;
while(res--)
{
ans[cnt++]=rmq(l,r);
l=ans[cnt-1]+1;
r=n-res;
}
int i=0;
while(str[ans[i]]=='0'&&i!=cnt-1)
{
i++;
}
for(;i<cnt;i++)
{
printf("%c",str[ans[i]]);
}
printf("\n");
}
return 0;
}