原题地址c++
题目大意:有一个\(n\)位数,其中的数字只有\(1\)~\(9\),不包括\(0\),每一个\(1\)~\(9\)的数字有一个映射,映射也在\(1\)~\(9\)中,如今咱们能够对这个\(n\)位数进行一些操做:选取这个数的一个区间,将区间中的数字所有替换成他们的映射数字,问:在只进行一次操做的状况下,更改后的数字最大为多少?spa
吐槽一句:某度翻译把题目翻译成了“只让这个数中的一个数字的映射生效,最大值是多少”,害得窝卡了1小时。。。翻译
其实这题很简单,咱们不妨先把\(x\)的映射称为\(f(x)\),咱们不断找\(x \le f(x)\)的在\(n\)位数中连续的\(x\),若是\(f(x)<x\),就退出寻找,可是,若是这样写,那么必定是错的,为何呢?c++11
好比说下面这个例子:code
5 18337 1 2 5 4 6 6 3 1 9
若是按照上面的思路,获得的答案仍然是\(18337\),为何呢?由于\(f(1)=1,f(8)=1\),因此在咱们找到“\(8\)”的时候,就会直接退出寻找,所以,咱们应该判断:若是有许多在\(n\)位数中连续的\(x\),它们都符合\(f(x)=x\),那么,这个子段就应该放弃寻找,去找另外的子段。get
\(Code:\)io
#pragma GCC diagnostic error "-std=c++11" #include <cstdio> using namespace std; template<class T>void r(T &a) { T s=0,w=1;a=0;char ch=getc(stdin); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getc(stdin);} while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getc(stdin);} a=w*s; } template<class T,class... Y>void r(T& t,Y&... a){r(t);r(a...);} char num[200010]; int a[15]; int flag; int main() { int n; r(n); gets(num); for(int i=1;i<=9;i++) r(a[i]); for(int i=0;i<n;i++) { if(!flag&&num[i]-'0'==a[num[i]-'0'])flag=-1; if(num[i]-'0'<=a[num[i]-'0'])num[i]=a[num[i]-'0']+'0',flag++; else if(flag)break; } printf("%s",num); return 0; }