P2880 [USACO07JAN] Balanced Lineup G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题暴力做的话会超时,因为n是1e6,q是1e5.复杂度就是O(n*m),也就是1e11
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N=1e6+10;
int a[N];
int main()
{
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i];
while(q--)
{
int maxn=-INF,minn=INF;
int l,r;cin>>l>>r;
for(int i=l;i<=r;i++)
{
maxn=max(maxn,a[i]);
minn=min(minn,a[i]);
}
cout<<maxn-minn<<endl;
}
return 0;
}
正解是RMQ算法,就是在O(1)时间内求出极值.RMQ算法的视线有很多种,最常用的是st表
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=180010;
int maxn[N][22],minn[N][22];
//maxnn存最大值 minn存最小值
int ST(int l,int r)
{
int s=log2(r-l+1);
//log2(r-l+1)是以2为底的对数,写成等式就是,2的log2(r-l+1)次方等于(r-l+1);
int x=max(maxn[l][s],maxn[r-(1<<s)+1][s]); //区间最大
int y=min(minn[l][s],minn[r-(1<<s)+1][s]);
//神奇的冻柜方程QWQ,记下来就好,反正不长
return x-y;
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>maxn[i][0];
minn[i][0]=maxn[i][0];
}
//这个循环的上界决定于数据的大小,即2的21次方大于数据,如果数据在大上界调高,logn是这个循环QWQ
for(int i=1;i<=21;i++)
{
for(int j=1;j+(1<<i)<=n+1;j++) //接进于n,算成n,其实没那么大
{
maxn[j][i]=max(maxn[j][i-1],maxn[j+(1<<(i-1))][i-1]);
minn[j][i]=min(minn[j][i-1],minn[j+(1<<(i-1))][i-1]);
}
}
for(int i=1;i<=m;i++)//O(1)调用开始
{
int l,r;cin>>l>>r;
cout<<ST(l,r)<<endl;
}
}
int main()
{
int t=1;
while(t--)
{
solve();
}
return 0;
}