题目思路:
题目要求删除m个数之后的最小值,我们可以反过来求,直接在这n个数里面选n-m个数,这样更加方便。
我们第一次挑选一定是从第一位到第m+1位中间选取一个,因为如果我们选的是第m+2位的话,那么之后我们只能选m+2后面的位数,但此时我们已经删掉了m+1位数了。
所以我们选取时区间的最右端从m+1开始,一直到n。
最左端就从1开始,下一次的右端点就是这次选取出来的数的右边第一位
这样我们选取的区间就完全清楚了
选取的时候用rmq的查询功能找到区间内最小的数的位置就好了
最后输出要注意清楚前导零
ac代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 5e4+50;
const int inf = 0x1f1f1f1f;
const int mod = 2333;
char a[maxn];
int num[maxn],m,dp[maxn][25],ans[maxn];
int n;
//因为我们需要得到的不是最小的数值 而是最小值的位置所以重新定义一个min
int minx(int x,int y)
{
return num[x]<=num[y]?x:y;
}
void rmq()
{
for(int i=1;i<=n;i++)
dp[i][0]=i;
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
dp[i][j]=minx(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r)
{
int i=0;
while(l+(1<<i)-1<=r)
{
i++;
}
i--;
return minx(dp[l][i],dp[r-(1<<i)+1][i]);
}
int main()
{
while(~scanf("%s%d",a,&m))
{
n=strlen(a);
for(int i=1;i<=n;i++)
{
num[i]=a[i-1]-'1'+1;
}
rmq();
int pos=1;
for(int i=1;i<=n-m;i++)
{
pos=query(pos,i+m);
ans[i]=num[pos++];
}
int flag=0;
int i;
for(i=1;i<=n-m;i++)
{
if(ans[i]!=0)
break;
}
if(i>n-m)
printf("0\n");
else
{
for(int k=i;k<=n-m;k++)
{
printf("%d",ans[k]);
if(k==n-m)
}
printf("\n");
}
}
}