H. 数字游戏
给你一个N位数,从中去掉K个数字,能得到的最大的数是多少?
INPUT
有T测试数据,每组测试数据第一行由N和K2个整数组成(1 ≤ K < N ≤ 500 000),第二行是N位数(非0开头)。
OUTPUT
对每组数据输出去掉K个数字得到的最大数。
SAMPLE TESTS
IN | OUT |
3 4 2 1924 7 3 1231234 10 4 4177252841 | 94 3234 775841
|
删数问题解释:
采用的是利用队列的方式来进行的操作 ,每次进行10次即可找到最大值,总共寻找n-k个最大值就可以了,
例如
7 3
1 2 3 1 2 3 4
位置为 0 1 2 3 4 5 6
从0- 3 的位置上找到最大值
9个队列 0 1 2 3 4 5 6 7 8 9
位置 0 1 2
从9-0遍历 遇到队列非空切 left >遍历的位置时即可 选择 3;
left=2 即 选择3时的位置
然后记录下一个位置
9个队列 0 1 2 3 4 5 6 7 8 9
位置 0 1
3
让后从9-0遍历 到2时 将位置1踢走 然后 到1时 将位置0踢走,然后到3得出正确结果。
另一种算法:
将 所有的位置 都放到0-9 这个位置中 用一个区间来卡住,从9-0开始遍历,在区间左边的值pop,不管区间右边的值,如果遇到刚好在区间里面的值就是你要找到的值,以此值所在的位置当做左区间,右区间加1即可。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
queue<int> my[11];
char a[501000];
char b[501000];
int main()
{
int i,k,n,x,ji,left,max,j,flag,num;
scanf("%d",&x);
while(x--)
{
memset(b,'0',sizeof(b));
for(i=0;i<=9;i++)
{
while(my[i].empty()==0) //将队列里全部的值pop
{
my[i].pop();
}
}
ji=0;
scanf("%d %d",&n,&k);
scanf("%s",a);
for(i=0;i<=k;i++) //输入【】里面是值的大小 push的是值的位置
{
my[ a[i]-'0' ].push(i);
}
for(j=9;j>=0;j--)
{ if( my[j].empty()==0 ){ //如果不为空 将之赋给只包括正确答案的b数组内。
b[ji]=('0'+j);
ji++;
left=my[j].front();
my[j].pop(); break;}
}
max=k+1;
for(i=1;i<=n-k-1;i++)
{
my[ a[max]-'0'].push(max);
max++;
flag=0;
for(j=9;j>=0;j--)
{
while(my[j].empty()==0)
{
if(left>my[j].front() ){my[j].pop();continue;} //要注意这里的continue,因为没加 wa了好多次。
if(left<my[j].front() ){
flag=1;
b[ji]='0'+j;
ji++;
left=my[j].front();
my[j].pop();
break;}
}
if(flag==1)break;
}
}
b[ji]='\0';
printf("%s\n",b); 输出正确答案。
}
}