删数问题 典型的思维问题

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);    输出正确答案。
  }  
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值