一、翻译及算法分析
USACO来源的题经常一言不合就是奶牛,很多题目都和牛有关。言归正传,本题:
对于每天的挤奶工作,John 的 N 头牛总是以相同的序列排成一队。一天, John 决定选择一些牛组织一场比赛。为了简单起见,他会从挤奶队伍中挑选一个连续的奶牛队伍来玩这个游戏。然而,为了让所有的奶牛都玩得开心,它们的身高不应该相差太大。
(注意核心题面)
For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.
也就是要对每次查询,求区间的样本极差。这样用ST表处理即可。
二、代码及注释
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int maxn=50050;
const int inf=0x3f3f3f3f;
typedef vector<int> vt;
vt a;
int dmin[maxn][25];
int dmax[maxn][25];
int n,m;
inline int read(){
char ch=getchar();
int ans=0,f=1;
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans*f;
}
void ST_init_max(const vt& A){
int n=A.size();
for(int i=0;i<n;i++) dmax[i][0]=A[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=0;i+(1<<j)-1<n;i++){
dmax[i][j]=max(dmax[i][j-1],dmax[i+(1<<(j-1))][j-1]);
}
}
int st_max(int l,int r){ //求最大和求最小的函数是非常相似的(事实上只是把max全换成min而已),这里一定要在命名上统一好才行。可以复制到word里然后用替换功能。
int k=0;
while((1<<(k+1))<=r-l+1) k++;
return max(dmax[l][k],dmax[r-(1<<k)+1][k]);
}
void ST_init_min(const vt& A){
int n=A.size();
for(int i=0;i<n;i++) dmin[i][0]=A[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=0;i+(1<<j)-1<n;i++){
dmin[i][j]=min(dmin[i][j-1],dmin[i+(1<<(j-1))][j-1]);
}
}
int st_min(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(){
memset(dmin,inf,sizeof(dmin));
n=read();
m=read();
for(int i=0;i<n;i++){
a.push_back(read());
}
ST_init_max(a);
ST_init_min(a);
for(int i=0;i<m;i++){
int ll=read();
int rr=read();
ll--;
rr--;
cout<<st_max(ll,rr)-st_min(ll,rr)<<endl;
}
return 0;
}
三、作者
Bowen
本题题解、代码及注释均为作者原创,转载请注明。
作者技术水平有限,如有纰漏之处,敬请斧正。