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
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;
}