这个题是我这么好久以来第一个一遍过的题目了,我哭了。。。一个思路不是很清晰,正确性自己不是很敢确定的算法,写出来居然一遍过了。而且只用了40ms,O(N)的复杂度。
首先这个题目的方法就是单调队列。一个递减的单调队列。但是这个递减队列不能对所有数进行构造,如果最后有一个数特别大会将前面的都出队。
假设m=n-d;为结果的长度。我们舍下最后m-1个数不管,先看前面d+1个数,对前面这些书进行构造单调队列,
完成后输出对头(对头一定是确定的,因为最后只剩下m-1个数,如果将队头出列那么后面就凑不够m个数了)然后head++;
然后检索剩下的数没检索一个就输出对头并且head++,原因同上
代码如下
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int que[maxn],a[maxn],head,tail;
int main()
{
int n,d,m;
while(cin>>n>>d && n&&d){
m=n-d;
head=tail=0;
string st;
cin>>st;
for(int i=0;i<n;i++) a[i]=st[i]-'0';
for(int i=0;i<=d;i++){
if(head==tail) que[tail++]=a[i];
else if(head<tail){
while(head<tail&&que[tail-1]<a[i]) tail--;
que[tail++]=a[i];
}
}
printf("%d",que[head++]);
for(int i=d+1;i<n;i++){
if(head==tail) {
printf("%d",a[i]);
head++;tail++;
}
else if(head<tail){
while(head<tail && que[tail-1]<a[i]) tail--;
que[tail++]=a[i];
printf("%d",que[head++]);
}
}
printf("\n");
}
return 0;
}