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