G. Maximizar la cadena restante (pensamiento + enumeración violenta / optimización de pila monótona)

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


Título:

Dada una cadena de longitud n que contiene solo letras minúsculas, elimine todos los caracteres repetidos (uno para cada carácter), haga que la cadena restante sea lexicográficamente más grande y genere la cadena restante. n≤2 × 10 ^ 5

Ideas:

Si puede ser violento, piense primero en la violencia.

Descubrimos que la respuesta tiene una extensión máxima de 26. Entonces, primero cuente el número de diferentes tipos de letras, y la longitud de la respuesta es su tamaño.

Luego, para cada bit de la respuesta, podemos O (26) enumerar cada carácter. Luego considere, si se selecciona el carácter actual, la cantidad de caracteres diferentes que siguen es suficiente. Elija si tiene suficiente. Si no es suficiente, continúe enumerando.

Así que juzgue rápidamente si los tipos de caracteres diferentes son suficientes y preprocese el sufijo.

O (26 * 26 * n) == 1e8 (2.5s) es suficiente

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

Más tarde, el grupo dijo que era la pregunta original.

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

Este problema es utilizar la optimización de pila monótona.

Parece un truco borrar números

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

Para actualizarse

Supongo que te gusta

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/115258141
Recomendado
Clasificación