5864: 桃子的长号

http://www.tzcoder.cn/acmhome/problemdetail.do?&method=showdetail&id=5864

Description

C++课上,老师讲到了映射map,桃子觉得映射很神奇,可以把一个串变成一个数存储,也可以把一堆很大的数字变成很小的数字。为了加深对映射的印象,桃子出了下面这个题:

桃子将给你一个长的十进制数a,包含n个1-9的数字,你有一个映射函数f可以把x变成f(x)。

你可以执行以下操作不超过1次:选择一个非空的连续子段并把里面的每个数字x映射成f(x)。例如a=1337,f(1)=1,f(3)=5,f(7)=3,你将选择区间[2,3],并把3变成f(3)=5,最终得到1557。

现在你执行了操作不超过1次,你可以得到的最大数是多少。

 

Input

第一行一个整数T(1≤T≤95),代表有T组数据。

对于每组数据:

第一行为一个整数n(1≤n≤2*105),为十进制数a的长度。

第二行为n个数字组成的整数a:a1a2...an(1≤ai≤9)。

第三行为9个数字f(1),f(2),...,f(9),代表映射函数f。

数据保证∑n<=106。

 

Output

每组数据输出一行,代表桃子能得到的最大值。

 

Sample Input

3
 4
 1337
 1 2 5 4 6 6 3 1 9
 5
 11111
 9 8 7 6 5 4 3 2 1
 2
 33
 1 1 1 1 1 1 1 1 1

Sample Output

1557
99999
33

Source

TZOJ

Tag

 

思路:

实际上就是普通的贪心,对于给定的连续区间的映射,只要第一个大于原先的值,我们就这一步开始进行

不过另外要注意的是,连续的映射,如果有等于的 也要继续

2341144

1 3 4 5 。。。。

那么最大的结果肯定是3451155

#include<iostream> 
#include<cstdio>
#include<set>
#include<cmath>
#include<cstring>
using namespace std;

typedef long long ll;
int N;
int T;
const int MAXN = 2e5+10;
char arr[MAXN];
//bool is_ok[MAXN];
int f[10];
int main(){
	scanf("%d",&T);
	for(int i=0;i<T;i++){
		memset(arr,0,sizeof(arr));
		memset(f,0,sizeof(f));
		scanf("%d",&N);
		//getchar()  有没有都不影响 
		scanf("%s",arr);
//		printf("%s\n",arr);	
		for(int j=1;j<=9;j++){
			scanf("%d",&f[j]);	
		}
		int start = -1;
		for(int j=0;j<N;j++){
			int aa = arr[j]-'0';
			//编程细节,必须要先大于,后面的可以等于,否则就会出错 
			if((start == -1 && (f[aa]>(aa))) ||((f[aa]>=(aa)) && ( start == j))){
				printf("%c",f[aa]+'0');
				start = j+1;	
			}else{
				printf("%c",arr[j]);
			}
		}
		printf("\n");
	}
	return 0;
}