题目大意:
给你一串数,50,000个,询问200,000个区间,每次询问输出该区间最大值与最小值的差
分析:
这个因为不用修改,只需要查询,其实用树状数组也是可以的我觉得,但是因为还是有一个log50000,说不定真的会超时,所以还是选择用他给的这个O(1)复杂度的算法吧。
关于st算法:
就是首先预处理:
dp [ i ] [ j ] 表示 从第 i 个数开始 向后数
关于查询:
查询区间 [ a , b ] 就是 max { dp [ a ] [ k ] , dp [ b-
代码:
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
#define maxn 50500
int n,q;
int dmax[maxn][30];
int dmin[maxn][30];
int a[maxn];
void build()
{
for(int i=1;i<=n;i++)dmax[i][0]=a[i];
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
dmax[i][j]=max(dmax[i][j-1],dmax[i+(1<<(j-1))][j-1]);
}
}
for(int i=1;i<=n;i++)dmin[i][0]=a[i];
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
dmin[i][j]=min(dmin[i][j-1],dmin[i+(1<<(j-1))][j-1]);
}
}
}
int getmax(int l,int r)
{
int k=0;
while((1<<(k+1))<=r-l+1)k++;
return max(dmax[l][k],dmax[r-(1<<k)+1][k]);
}
int getmin(int l,int r)
{
int k=0;
while((1<<(k+1))<=r-l+1)k++;
return min(dmin[l][k],dmin[r-(1<<k)+1][k]);
}
int main()
{
while(cin>>n>>q)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build();
int a,b;
for(int i=1;i<=q;i++)
{
scanf("%d%d",&a,&b);
printf("%d\n",getmax(a,b)-getmin(a,b));
}
}
}
ST算法的xcx理解:
首先用一种很暴力的方法,如果我求出了任意一个区间的最大值,然后存起来,随查随用,那么查询就是完美的O(1)时间复杂度。但是这样预处理就太慢了,用动态规划应该也需要
后注:
这波魔板代码抄的真是爽,写了一下午比赛,ac4题,实在懒得想这个代码的细节了,回来要自己再好好写一道rmq的题。