题目描述
现给你n(n≤106)个整数,有k(0<k≤106)个询问,对于每个询问(L,R),回答(L,R)内的最大值为多少。
输入
输入共计2行。第一行两个整数n和k;第二行为n个整数,第三行到第k+2行为k个询问。
输出
共k行,每行为一个询问的最大值。
样例输入
10 2
3 2 4 5 6 8 1 2 9 7
1 8
2 9
样例输出
8
9
求区间最值,用rmq算法或树状数组求解
代码如下:
树状数组:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
const int MAXN =1000005;
int a[MAXN], h[MAXN];
int n, m;
int lowbit(int x)
{
return x & (-x);
}
void updata(int x)
{
int lx, i;
while (x <= n)
{
h[x] = a[x];
lx = lowbit(x);
for (i=1; i<lx; i<<=1)
h[x] = max(h[x], h[x-i]);
x += lowbit(x);
}
}
int query(int x, int y)
{
int ans = 0;
while (y >= x)
{
ans = max(a[y], ans);
y --;
for (; y-lowbit(y) >= x; y -= lowbit(y))
ans = max(h[y], ans);
}
return ans;
}
int main()
{
int i, j, x, y, ans;
char c;
while (scanf("%d%d",&n,&m)!=EOF)
{
for (i=1; i<=n; i++)
h[i] = 0;
for (i=1; i<=n; i++)
{
scanf("%d",&a[i]);
updata(i);
}
for (i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
ans = query(x, y);
printf("%d\n",ans);
}
}
return 0;
}
rmq:
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
int n,k,a[1000005];
int f[1000005][26];
void rmq()
{
for(int i=1;i<=n;i++)
f[i][0]=a[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int find(int l,int r)
{
int k=trunc(log2(r-l+1));
return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
rmq();
int l,r;
for(int i=1;i<=k;i++)
{
scanf("%d%d",&l,&r);
printf("%d\n",find(l,r));
}
return 0;
}