2020 ICPC · Torneo de prueba de la red Xiaomi 2do (Una pregunta 2020)

Portal

Título

Dar una cadena SSS (∣ S ∣ <= 1 e 5 | S | <= 1e5S <=1 e 5 ), solo hay tres caracteres de '0', '1' y '2' en la cadena. ¿Cuál es el número máximo de subsecuencias disjuntas "2020".

responder

Al observar las características de "2020", las estructuras izquierda y derecha son las mismas, por lo que se puede descomponer en dos subproblemas idénticos, a saber, cuántas primeras "20" cadenas y cuántas segundas "20" cadenas se pueden formar, y luego combinarlas Es la respuesta. El problema es cómo juzgar cuántas primeras "20" cadenas deben formarse. Obviamente, la enumeración violenta no es aceptable. En este momento, debemos pensar en la dicotomía. Si desea usar la dicotomía, primero debe determinar si cumple con la naturaleza monótona de la dicotomía; piénselo y averigüe Si puede formar XXLas subsecuencias X "2020" obviamente también pueden formarX - 1 X-1X-1 subsecuencia "2020", de lo contrario, si no puede formarXXLas subsecuencias X "2020" obviamente no se pueden combinar enX + 1 X + 1X+1 subsecuencia.

Entonces, de acuerdo con la naturaleza dicotómica, entonces el número de la primera cadena "20" se dicotomiza, que es la respuesta dicotómica, y los pasos específicos son mirar el código.

Código AC

/*******************************
*   Coder : He Shuo.           *
*   Type : Original Work       *
*******************************/
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 55;

int n;
char s[MAXN];

int check(int x)
{
    
    
    int a1 = x,a2 = 0,a3 = 0,a4 = 0;
    ///a1 表示第一个"20"字符中2还需要多少个,a2则是'0'还需要多少个
    ///a3 表示第二个"20"字符中2还需要多少个,a4则是'0'还需要多少个
    
    for(int i = 1;i <= n;i ++)
    {
    
    
        if(s[i] == '2')
        {
    
    
            if(a1)a1 --,a2 ++;///来了一个'2',优先把第一个"20"中的'2'达成数量要求;
            else if(a3)a3 --,a4 ++;///达成之后就填第二个"20"的'2';
        }
        else if(s[i] == '0')
        {
    
    
            if(a2)a2 --,a3 ++;///来了一个'0',也是优先把第一个"20"中的'0'达成数量要求;
            else if(a4)a4 --;///达成之后就填第二个"20"的'0';
        }
    }
    if(a1 == 0 && a2 == 0 && a3 == 0 && a4 == 0)return 1;///所有数量都达成之后说明当前x符合条件
    return 0;///否则就不行
}

int main()
{
    
    
	while(scanf("%d",&n) + 1)
    {
    
    
        scanf("%s",s + 1);
        int l = 0,r = n / 4;///答案边界为[0,n/4],很显然的吧。
        while(l < r)
        {
    
    
            int mid = l + r >> 1;
            if(check(mid))l = mid + 1;
            else r = mid;
        }
        if(check(l) == 0)l --;///看看当前l符不符合,不符合就答案减一(本蒟蒻二分就喜欢这么写,保险一点)
        printf("%d\n",l);
    }

}

Supongo que te gusta

Origin blog.csdn.net/qq_43814654/article/details/109407083
Recomendado
Clasificación