传送门
给出一个有N个数的序列,编号0 - N - 1。进行Q次查询,查询编号i至j的所有数中,最大的数是多少。
例如: 1 7 6 3 1。i = 1, j = 3,对应的数为7 6 3,最大的数为7。(该问题也被称为RMQ问题)
Input
第1行:1个数N,表示序列的长度。(2 <= N <= 10000) 第2 - N + 1行:每行1个数,对应序列中的元素。(0 <= S[i] <= 10^9) 第N + 2行:1个数Q,表示查询的数量。(2 <= Q <= 10000) 第N + 3 - N + Q + 2行:每行2个数,对应查询的起始编号i和结束编号j。(0 <= i <= j <= N - 1)
Output
共Q行,对应每一个查询区间的最大值。
Input示例
5 1 7 6 3 1 3 0 1 1 3 3 4
Output示例
7 7 3
分析:
1·用暴力的方法也能过
for(int i = 0; i < n; i++)
cin >> a[i];
int q;
cin >> q;
while(q--)
{
int l,r;
cin >> l >> r;
int ans = 0;
for(int i = l; i <= r; i++)
ans = max(a[i],ans);
cout << ans << endl;
}
2·如果遇到数据很大的话,当然可以使用线段树来优化,可以说是很裸的模板。
/* ****
* 线段树求区间最大值
* ****/
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1e5+10;
const int MAXN1 = MAXN*4;
int a[MAXN];
int maxs[MAXN1];
void pushup(int root)
{
maxs[root] = max(maxs[root<<1],maxs[root<<1|1]);
}
void build(int L,int R,int rt)
{
if(L == R)
{
maxs[rt] = a[L];
return ;
}
int M = (L+R) >> 1;
build(L,M,rt<<1);
build(M+1,R,rt<<1|1);
pushup(rt);
}
int query(int rt, int l, int r ,int L, int R)
{
if(l == L && r == R)
{
return maxs[rt];
}
int ans = 0;
int M = (L+R)>>1;
if(r<=M)
ans = max(query(rt<<1,l,r,L,M), ans);
else if(l > M)
ans = max(query(rt<<1|1,l,r,M+1,R), ans);
else
{
int t1 = query(rt<<1,l,M,L,M);
int t2 = query(rt<<1|1,M+1,r,M+1,R);
ans = max(t1, max(t2,ans) );
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
int n,q;
int l,r;
memset(a,0,sizeof(a));
cin >> n;
for(int i = 1;i <= n; i++)
cin >> a[i];
build(1,n,1);
cin >> q;
while(q--)
{
cin >> l >> r;
l++, r++;
int ans = query(1,l,r,1,n);
cout << ans << endl;
}
system("pause");
return 0;
}