Explicación súper detallada # C. El número con más apariciones (el valor más frecuente de POJ3368)

tema


tren de pensamiento

analizar

Dado que esta pregunta puede acumular el número de apariciones de elementos y luego consultar el valor máximo del intervalo , se puede resolver usando ST . mx[i][j] representa el valor máximo del intervalo [i.2^j-1] y la longitud del intervalo es 2^j .

Pasos del algoritmo

1.

Los elementos iguales de la secuencia no decreciente deben ser adyacentes , cada elemento se compara con el elemento anterior y el número de repeticiones se acumula y almacena en mx[i][0] .

2.

Crear tabla ST .

3.

Consulta el valor máximo del intervalo [1,r] . Si el primer número es igual al número anterior , primero cuente el número de apariciones del primer número en el intervalo de consulta [l, r] , luego consulte el valor máximo de los intervalos restantes y luego calcule el valor máximo de los dos .

detalles

Por ejemplo, tomemos un ejemplo:

1. Inicialización

Acumule y almacene el número de apariciones de elementos en la muestra de entrada en mx[i][0]

for(int i = 1; i <= n; i++)
{
  scanf("%lld",&a[i]);
  if(a[i] == a[i - 1]) mx[i][0] = mx[i - 1][0] + 1;
  else mx[i][0] = 1;
}

2. Cree ST .

void zynb()
{
  int r = log2(n);
  for(int i = 1; i <= r; i++)
    for(int j = 1; s[i] + j - 1 <= n; j++)
      mx[j][i] = max(mx[j][i - 1],mx[j + s[i - 1]][i - 1]);
}

3. Consulta.

La primera consulta de ejemplo es 2 3:

Consulta el número de apariciones del valor más frecuente en el intervalo [2, 3]. Primero, t = l = 2, porque a [2] = a [1], t++, es decir, t = 3; en este momento a [3] ≠ a [2], t - l = 1, RMQ(t , r) = RMQ(3, 3) = 1, encuentre el valor máximo de los dos y obtenga el número de apariciones del valor más frecuente en el intervalo [2, 3] es 1. Nota: RMQ(2, 3) no se puede consultar directamente,

El ejemplo de la segunda consulta es 1 10:

Consulta el número de apariciones del valor más frecuente en el intervalo [1, 10]. Primero, t = l =1, a [1] ≠ a [0], t - l =0, RMQ(t,r)=RMQ(1,10)=4, encuentra el máximo de los dos, obtén [1 , 10] El número de apariciones del valor más frecuente en el intervalo es 4.

El ejemplo de la tercera consulta es 5 10:

查询[5, 10]区间最频繁值的出现次数。首先,t = l =5,因为a [5] = a [4],t ++,即t =6;a[6] = a [5],t++,即t =7;此时a [7]≠a [6],t -l =2,RMQ(t , r )=RMQ(7,10)=3,求两者的最大值,得到[5, 10]区间最频繁值的出现次数为3。

若直接查询RMQ(5, 10)=4,但是a [5]在[5, 10]区间的出现次数是2,则不是4。因此若a [l]和前一个数a [l -1]相等,则需要先统

计a [l ]在[l , r ]区间的出现次数,再查询剩余区间的最值,比较

两者的最大值。

int weqsb(int x,int y)
{
  if(x > y) return 0;
  int r = log2(y - x + 1);
  int t1 = max(mx[x][r],mx[y - s[r] + 1][r]);
  return t1;
}

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int s[10000001],n,q,a[10000001],mx[100001][101],t,l,r,ans;
void zynb()
{
  int r = log2(n);
  for(int i = 1; i <= r; i++)
    for(int j = 1; s[i] + j - 1 <= n; j++)
      mx[j][i] = max(mx[j][i - 1],mx[j + s[i - 1]][i - 1]);
}
int weqsb(int x,int y)
{
  if(x > y) return 0;
  int r = log2(y - x + 1);
  int t1 = max(mx[x][r],mx[y - s[r] + 1][r]);
  return t1;
}
signed main()
{
  s[0] = 1;
  for(int i = 1; i <= 60; i++) s[i] = s[i - 1] * 2;
  while(1)
  {
    memset(mx,0,sizeof(mx));
    scanf("%lld",&n);
    if(n == 0) break;
    scanf("%lld",&q);
    for(int i = 1; i <= n; i++) mx[i][0] = 1;
    for(int i = 1; i <= n; i++)
    {
      scanf("%lld",&a[i]);
      if(a[i] == a[i - 1]) mx[i][0] = mx[i - 1][0] + 1;
      else mx[i][0] = 1;
    }
    zynb();
    while(q--)
    {
      scanf("%lld%lld",&l,&r);
      t = l;
      while(t <= r && a[t] == a[t - 1]) t++;
      printf("%lld\n",max(weqsb(t,r),t - l));
    }
  }
  return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weq2011/article/details/128767599
Recomendado
Clasificación