您的位置:首页 > 其它

RMQ(模板 ST 区间最值,频繁的间隔时间)

2015-07-27 13:51 357 查看
PS:

介绍:/article/1752977.html

RMQ算法。是一个高速求区间最值的离线算法,预处理时间复杂度O(n*log(n))。查询O(1)。所以是一个非常高速的算法,当然这个问题用线段树相同可以解决。

1、求区间的最大值和最小值!

代码例如以下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
const int MAXN = 100117;
int n,query;
int num[MAXN];

int F_Min[MAXN][20],F_Max[MAXN][20];

void Init()
{
for(int i = 1; i <= n; i++)
{
F_Min[i][0] = F_Max[i][0] = num[i];
}

for(int i = 1; (1<<i) <= n; i++)  //按区间长度递增顺序递推
{
for(int j = 1; j+(1<<i)-1 <= n; j++)  //区间起点
{
F_Max[j][i] = max(F_Max[j][i-1],F_Max[j+(1<<(i-1))][i-1]);
F_Min[j][i] = min(F_Min[j][i-1],F_Min[j+(1<<(i-1))][i-1]);
}
}
}

int Query_max(int l,int r)
{
int k = (int)(log(double(r-l+1))/log((double)2));
return max(F_Max[l][k], F_Max[r-(1<<k)+1][k]);
}

int Query_min(int l,int r)
{
int k = (int)(log(double(r-l+1))/log((double)2));
return min(F_Min[l][k], F_Min[r-(1<<k)+1][k]);
}

int main()
{
int a,b;
scanf("%d %d",&n,&query);
for(int i = 1; i <= n; i++)
scanf("%d",&num[i]);
Init();
while(query--)
{
scanf("%d %d",&a,&b);
printf("区间%d到%d的最大值为:%d\n",a,b,Query_max(a,b));
printf("区间%d到%d的最小值为:%d\n",a,b,Query_min(a,b));
printf("区间%d到%d的最大值和最小值仅仅差为:%d\n",a,b,Query_max(a,b)-Query_min(a,b));
}
return 0;
}


2、求区间内出现次数最多的数字出现的次数。

代码例如以下:

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const int maxn = 100017;
int num[maxn], f[maxn], MAX[maxn][20];
int n;
int max(int a,int b)
{
return a>b ?

a:b;
}
int rmq_max(int l,int r)
{
if(l > r)
return 0;
int k = log((double)(r-l+1))/log(2.0);
return max(MAX[l][k],MAX[r-(1<<k)+1][k]);
}
void init()
{
for(int i = 1; i <= n; i++)
{
MAX[i][0] = f[i];
}
int k = log((double)(n+1))/log(2.0);
for(int i = 1; i <= k; i++)
{
for(int j = 1; j+(1<<i)-1 <= n; j++)
{
MAX[j][i] = max(MAX[j][i-1],MAX[j+(1<<(i-1))][i-1]);
}
}
}
int main()
{
int a, b, q;
while(scanf("%d",&n) && n)
{
scanf("%d",&q);
for(int i = 1; i <= n; i++)
{
scanf("%d",&num[i]);
}
sort(num+1,num+n+1);
for(int i = 1; i <= n; i++)
{
if(i == 1)
{
f[i] = 1;
continue;
}
if(num[i] == num[i-1])
{
f[i] = f[i-1]+1;
}
else
{
f[i] = 1;
}

}

init();

for(int i = 1; i <= q; i++)
{
scanf("%d%d",&a,&b);
int t = a;
while(t<=b && num[t]==num[t-1])
{
t++;
}
int cnt = rmq_max(t,b);
int ans = max(t-a,cnt);
printf("%d\n",ans);
}
}
return 0;
}
/*
10 3
-1 -1 1 2 1 1 1 10 10 10
2 3
1 10
5 10
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: