P2880 [USACO07JAN] Balanced Lineup G 题型:RMQ算法->st表 模板题

78 阅读2分钟

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;
}

image.png

正解是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;	
} 


image.png