題目描述:
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?
輸入:
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.
輸出:
For each case, output the minimum result you can get in one line.
If the result contains leading zero, ignore it.
樣例輸入:
178543 4
1000001 1
100001 2
12345 2
54321 2
樣例輸出:
13
1
0
123
321
思路分析:
其實這一題就是求數列刪出後的最小值。
我們可以先用RMQ求出數列區間的最小值。
之後我們要取len-m個數,那麼我們的第一個區間邊界就是1到m+1,爲什麼呢。
我們要取len-m個數,那麼就算是後面的都取,則是len-m+1,所以區間就是[1,m+1]。
最後我們在尋找過程中用暴力就可以尋找下一個節點的左端點(所尋的數的位置)。
代碼實現:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int len,n,m,dp[1005][25],s1[1005];
char s[1005];
int Get_quary(int l,int r)
{
int k=(int)(log(double(r-l+1))/log(double(2)));
return min(dp[l][k],dp[r-(1<<k)+1][k]);
}
int main()
{
while(scanf("%s%d",s,&m)!=-1)
{
len=strlen(s);
int tot=0;
if(m<=0)
{
puts(s);
continue;
}
for(int i=0;i<len;i++)
dp[i][0]=s[i]-'0';
for(int j=1;(1<<j)<=len;j++)
for(int i=0;i+(1<<j)-1<len;i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
int l=0,r=m;
while(l<=r)
{
int p=Get_quary(l,r);
tot++;
s1[tot]=p;
int i=l;
for(;i<=r;i++)
if(p+'0'==s[i])
break;
l=i+1;
r++;
}
int i;
for(i=1;i<tot;i++)
if(s1[i]>0)
break;
if(i==tot)
{
printf("0\n");
continue;
}
for(;i<tot;i++)
printf("%d",s1[i]);
printf("\n");
memset(dp,0,sizeof(dp));
}
}