ST表——题目:A Magic Lamp

题目:A Magic Lamp

题目概述

时间限制:1秒 内存限制:128M

题目描述

一个整数(最多可以包含 1100 位数字。),删除 m m m m < = m<= m<=整数的位数) 位数字,使剩余的数字最小(注:不能改变数字的顺序,要删除前导零,给定的整数将不包含前导零)。
(有若干组测试用例)。

样例输入

178543 4 
1000001 1
100001 2
12345 2
54321 2

样例输出

13
1
0
123
321

解题思路

思路:用ST表找出保留的整数(保留的是必须要选出这个数的区间内最小的数)并输出。

  1. 循环输入各项数据
while(cin>>s>>m){
  1. ST表初始化
int len=s.size();
for(int i=0;i<len;i++){
	min_f[i+1][0].first=s[i];
	min_f[i+1][0].second=i+1;
}
  1. ST表打表。min_f[i][j]表示从i开始 2 j 2^j 2j个数位中的最小数。
for(int j=1;j<=log2(len);j++){
	for(int i=1;i+pow(2,j)-1<=len;i++){
		min_f[i][j]=min(min_f[i][j-1],min_f[i+(1<<j-1)][j-1]);
	}
}

4.输出每一位,flag用来处理前导零,tmp是要保留的位数。

int tmp=s.size()-m;
	int l=1,r=m+1;
	bool flag=false;
	while(tmp--){
		int k=log2(r-l+1);
		pair<char,int> ans=min(min_f[l][k],min_f[r-(1<<k)+1][k]);
		if(ans.first!='0'){
			flag=true;
		}
		if(flag){
			cout<<ans.first;
		}
		l=ans.second+1;
		r++;
	}
	if(!flag){
		cout<<0;
	}
	cout<<endl;

AC代码

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
pair<char,int> min_f[1105][30];
string s;
int m;
void st(){
	int len=s.size();
	for(int i=0;i<len;i++){
		min_f[i+1][0].first=s[i];
		min_f[i+1][0].second=i+1;
	}
	for(int j=1;j<=log2(len);j++){
		for(int i=1;i+pow(2,j)-1<=len;i++){
			min_f[i][j]=min(min_f[i][j-1],min_f[i+(1<<j-1)][j-1]);
		}
	}
}
int main(){
	while(cin>>s>>m){
		st();
		int tmp=s.size()-m;
		int l=1,r=m+1;
		bool flag=false;
		while(tmp--){
			int k=log2(r-l+1);
			pair<char,int> ans=min(min_f[l][k],min_f[r-(1<<k)+1][k]);
			if(ans.first!='0'){
				flag=true;
			}
			if(flag){
				cout<<ans.first;
			}
			l=ans.second+1;
			r++;
		}
		if(!flag){
			cout<<0;
		}
		cout<<endl;
	}
	return 0;
} 

知识点:ST表

原理及简介

ST表是一种用来处理可重复贡献问题的特殊动态规划算法。
什么是可重复贡献问题呢?
就是一个元素多次参与答案的计算,不影响结果的问题就是可重复贡献问题。如:区间最大值,区间最小值,区间最小公倍数,区间最大公约数。
ST表的特别之处在于它的f[i][j]表示从编号为i的元素开始 2 j 2^j 2j个元素的最优答案。
状态转移方程: f [ i ] [ j ] = m i n ( f [ i ] [ j − 1 ] , f [ i + ( 1 < < j − 1 ) ] [ j − 1 ] ) f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]) f[i][j]=min(f[i][j1],f[i+(1<<j1)][j1])
它的状态转移方程是怎么来的呢?
就是把要求的区间平均分成两份,求两个区间的最终答案。
但要查的区间元素数往往不是2的次方,怎么办呢?
我们可以找出最接近并且小于的它的2的次方,然后把从头往后找那个2的次方个元素的最优值和从尾往前找那个2的次方个元素的最优值再求一遍最优就是正确答案。由于是可重复贡献问题,有重复部分也不怕。

代码实现

void st(){
	int len=s.size();
	for(int i=0;i<len;i++){
		min_f[i+1][0].first=s[i];
		min_f[i+1][0].second=i+1;
	}
	for(int j=1;j<=log2(len);j++){
		for(int i=1;i+pow(2,j)-1<=len;i++){
			min_f[i][j]=min(min_f[i][j-1],min_f[i+(1<<j-1)][j-1]);
			//函数按实际情况替换
		}
	}
}

总结

这次我主要分享了题目:A Magic Lamp的解法,和ST表的相关信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值