G. Maximize the Remaining String (thinking + violent enumeration/monotonic stack optimization)

https://codeforces.com/contest/1506/problem/G


Title:

Given a string of length n containing only lowercase letters, delete all repeated characters (one for each character), make the remaining string lexicographically largest, and output the remaining string. n≤2×10^5

Ideas:

If you can be violent, think about violence first.

We found that the answer is at most 26 in length. So first count the number of different types of letters, and the length of the answer is its size.

Then for each bit of the answer, we can O(26) enumerate each character. Then consider, if the current character is selected, the number of different characters that follow is enough. Choose if you have enough. If it is not enough, continue enumerating.

So quickly judge whether the types of different characters are enough, and preprocess the suffix.

O(26*26*n)==1e8 (2.5s) is enough

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+1000;
typedef int LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
char str[maxn];
LL sum[maxn];///后缀不同种类数字的个数
bool st[maxn][30];///后缀每个种类数字的存在状态
bool del[maxn];
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL t;cin>>t;
  while(t--){
     cin>>(str+1);
     LL n=strlen(str+1);
     for(LL i=0;i<n+10;i++) sum[i]=0,del[i]=0;
     for(LL i=0;i<n+10;i++){
        for(LL j=0;j<=29;j++) st[i][j]=0;
     }
     for(LL i=n;i>=1;i--){
         sum[i]=sum[i+1];
         for(LL j=1;j<=26;j++){
            st[i][j]=st[i+1][j];
         }
         if(st[i][str[i]-'a'+1]==0){
            st[i][str[i]-'a'+1]=1;
            sum[i]++;
         }
     }
     LL m=sum[1];
     vector<char>v;
     LL op=1;
     for(LL l=1;l<=m;l++){
        for(char c='z';c>='a';c--){
            if(st[op][c-'a'+1]==false) continue;
            bool flag=0;
            for(LL i=op;i<=n;i++){
                if(flag){
                    if(st[i][c-'a'+1]==1){
                        st[i][c-'a'+1]=0;
                        sum[i]--;
                    }
                    if(str[i]==c) del[i]=1;
                }
                if(del[i]) continue;
                if(str[i]==c){
                    LL temp=sum[i+1];///后面的有效种类个数
                    if(st[i+1][c-'a'+1]) temp--;///如果涵盖当前字母,--;
                    if(temp>=m-l){
                        flag=1;
                        op=i+1;
                    }
                }
            }
            if(flag){
                v.push_back(c);
                break;
            }
        }
     }
     for(auto i:v){
        cout<<i;
     }
     cout<<"\n";
  }
return 0;
}

Later, the group said it was the original question.

https://ac.nowcoder.com/acm/contest/12606/E

This problem is to use monotonic stack optimization.

It seems to be a trick to delete numbers

https://codeforces.ml/gym/102890/problem/M

To be updated

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/115258141