2 条题解

  • 1
    @ 2023-5-26 23:32:07

    *想要字典序最小,要让较小的往前靠,所以遍历到一个字符时看一下这个字符后面的字符有没有比他小的

    1. 有比当前字符小的,让后面的前移,让当前的字符变成min(d+1,9),插到合适的位置
    2. 没有比当前小的,就要把这个字符存储起来输出
    3. 貌似这种遍历方法需要借助双层循环,但是|s|<1e5,会超时,需要借助一个cnt数组,先把所有的字符转成数字存起来,再次循环这个串时只需要减去当前的字符,在从0循环到9,看有没有比当前小的,在按1,2过程处理
    4. 输出时,同样从0循环到9,如若这个数不是0,输出总数量的该数,,这样可以保证按升序输出,时间复杂度O(10*x.szie()),可顺利AC本题!
    • 代码如下
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int cnt[20];
    int ans[20];
    const int N=2e5+10;
    void solve() {
    	memset(cnt,0,sizeof(cnt));
    	memset(ans,0,sizeof(ans));
    	string x;
    	cin>>x;
    	for(int i=0; i<x.size(); i++) {
    		int p=x[i]-'0';
    		cnt[p]++;
    	}
    	int flag=0;
    	for(int i=0; i<x.size(); i++) {
    		int o=x[i]-'0';
    		cnt[o]--;
    		for(int j=0; j<=9; j++) {
    			if(cnt[j]&&j<x[i]-'0') {
    				flag=1;
    				int p=x[i]-'0';
    				if(p==9)
    				ans[9]++;
    				else
    				ans[(p)+1]++;
    				break;
    			}
    		}
    		if(!flag)
    		ans[o]++;
    		flag=0;
    	}
    	for(int i=0;i<=9;i++)
    	{
    		if(ans[i])
    		{
    			for(int j=1;j<=ans[i];j++)
    			{
    				cout<<i;
    			}
    		}
    	}
    	cout<<endl;
    }
    int main() {
    	std::ios::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	int t;
    	cin>>t;
    	while(t--) {
    	  solve();
    	}
    }
    
    • 0
      @ 2022-10-15 20:42:53

      由题目可知,在经过一定操作后你需要把字符串变为0~9顺序排序的字符串。

      操作只能使数字变大,因此,较小的数要保留。如果一个数字00在字符串的末尾,为了保留它,你需要把00前面所有字符串都删掉重新插入。

      统计090……9数字最后出现的位置,对于每一个位置,如果前面有大于这个数字的,就要删除它,让它的值+1,插入到合适的位置。

      • 1

      信息

      ID
      811
      时间
      1000ms
      内存
      256MiB
      难度
      8
      标签
      递交数
      162
      已通过
      30
      上传者