思路
一次变换会变小说明是去掉的s[i]存在s[i+1]<s[i],同时1<j<i的时候前后序列的是完全一致的,此时就是变换成功的。那么会考虑从左到右,优先去掉靠左的时候的上述情况,去掉后整体的长度就会减小1,减小之前的长度就是我们直接增大的长度,相当于直接跳过了S中的一节。这个过程我们可以用栈来维护,没遇到比自己小的下一位就存进去,否则就出栈,同时跳过一节,注意在出栈的时候可能不止会连续出一次,这时候应该处理完栈顶和准备入栈的元素之间的关系再入栈,保证栈的有序,因为最后是要输出第n个,所以用vector来模拟栈,方便输出。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1007;
const int mod = 998244353;
int a[N];
int mp[N][N];
void solve()
{
string s;
ll n;
cin>>s>>n;
n--;
int curlen=s.length();
s+=('a'-1);//
vector<char> st;
bool flag=n<curlen;
for(int i=0;i<s.length();i++){
while(st.size()>0&&!flag&&st.back()>s[i]){
n-=curlen;
curlen--;
st.pop_back();
if(n<curlen) flag=true;
}
st.push_back(s[i]);
}
cout<<st[n];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
在s的尾部添加一个比a小的字符,保证了如果原本序列就是上升序列到最后可以从后往前依次出栈。