A Magic Lamp

 A Magic Lamp

求一个数删除m位数字的最小值,且不允许更改数字顺序。

输入

若干行,每行包含一个整数和m;

输出

最小的结果,无前导零

输入样例

  1. 178543 4
  2. 1000001 1
  3. 100001 2
  4. 12345 2
  5. 54321 2

输出样例

  1. 13
  2. 1
  3. 0
  4. 123
  5. 321
 思路

设这个数为1651708 m为1

一般我们想到的是直接删最大值‘7’,结果为165108

但 是 如 果 删 除 ‘ 6 ’  ,结果为 151708

很明显165108>151708

所以 ,思路如下

1.从最高位开始遍历,删除上升序列的最后一个。如1651708

2.如果最高位无上升序列,则删除最高位数字。如987654321

3.遍历m次,每次删除符合1或2要求的数

相反的删除m个数,就是保留n-m个数

保留的第一个数x_{1}(下标)一定包含在[1,m+1]中

保留第二个数包含在[x_{1}+1,m+2]中。

那么解题思路为查找区间[x,y]最小值并记录

原代码如下

#include<bits/stdc++.h>
using namespace std;
int m;
char ch[1200];
pair<char,int> f[1200][11];
void adb(){
	int len=strlen(ch);
	for(int i=0;i<len;i++)
	{
		f[i][0]=make_pair(ch[i],i+1);
	}
	for(int j=1;(1<<j)<=len;j++)
	{
		for(int i=1;i+(1<<j)-1<=len;i++)
		{
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
}
int main(){
	while(cin>> ch >> m){
		adb();
		int l=1,r=m+1,as=strlen(ch)-m;
		int oi=0;
		while(as--){
			int k=log2(r-l+1);

			char an1=min(f[l][k], f[r - (1 << k) + 1][k]).first;
			int an2=min(f[l][k], f[r - (1 << k) + 1][k]).second;
			

			if(an1!='0'||oi){
				cout<< an1;
				oi=1;
			}

			l=an2+1;
			r++;
		}
		
		if(oi==0){
			cout<< 0; 
		}
		cout<< endl;
	}
	return 0;
}

之后发现样例错误。

第二次调试代码

#include<bits/stdc++.h>
using namespace std;
int m;
char ch[1200];
pair<char,int> f[1200][11];
void adb(){
	int len=strlen(ch);
	for(int i=0;i<len;i++)
	{
		f[i][0]=make_pair(ch[i],i+1);
	}
	for(int j=1;(1<<j)<=len;j++)
	{
		for(int i=1;i+(1<<j)-1<=len;i++)
		{
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
}
int main(){
	while(cin>> ch >> m){
		adb();
		int l=1,r=m+1,as=strlen(ch)-m;
		int oi=0;
		while(as--){
			int k=log2(r-l+1);
			cout<< l << " " << r << " "<< k << " " << r-(1<<k)+1; 
			char an1=min(f[l][k], f[r - (1 << k) + 1][k]).first;
			int an2=min(f[l][k], f[r - (1 << k) + 1][k]).second;
			
			cout<< "a";
			if(an1!='0'||oi){
				cout<< an1;
				oi=1;
			}
			cout<< "b";
			l=an2+1;
			r++;
		}
		
		if(oi==0){
			cout<< 0; 
		}
		cout<< endl;
	}
	return 0;
}

发现K越界了。

AC代码

#include<bits/stdc++.h>
using namespace std;
int m;
char ch[1200];
pair<char,int> f[1200][11];
void adb(){
	int len=strlen(ch);
	for(int i=1;i<=len;i++)
	{
		f[i][0]=make_pair(ch[i-1],i);
	}
	for(int j=1;(1<<j)<=len;j++)
	{
		for(int i=1;i+(1<<j)-1<=len;i++)
		{
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
}
int main(){
	while(cin>> ch >> m){
		adb();
		int l=1,r=m+1,as=strlen(ch)-m;
		int oi=0;
		while(as--){
			int k=log2(r-l+1);

			char an1=min(f[l][k], f[r - (1 << k) + 1][k]).first;
			int an2=min(f[l][k], f[r - (1 << k) + 1][k]).second;
			

			if(an1!='0'||oi){
				cout<< an1;
				oi=1;
			}

			l=an2+1;
			r++;
		}
		
		if(oi==0){
			cout<< 0; 
		}
		cout<< endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值