//题目大意:第一行给出N,Q两个数,(1<=N<=50000;1<=Q<=200000)接下来n行每一行有一个数, //再接下来有Q组查询,每行查询给出一个区间[l,r](1<=l<=r<=N),输出该区间内最大值和最小值的差值。 //输入 //6 3 //1 //7 //3 //4 //2 //5 //1 5 //4 6 //2 2 //输出 //6 //3 //0 #include <iostream> #include <algorithm> #include <cmath> #include <cstring> using namespace std; int a[50005]; int fmaxn[50005][50];//fmax[i][j]表示从第i位起,向后2^j范围内的最大值 int fminn[50005][50];//fmin[i][j]表示从第i位起,向后2^j范围内的最小值 int n,q; void ST_work(){//建立ST表 for(int i=0;i<n;++i) { fmaxn[i][0]=fminn[i][0]=a[i];//表示区间[i,i]范围,即初值 } int t=log(n)/log(2)+1;//即要满足(1<<j)<=n for(int j=1;j<t;++j) for(int i=0;i<=n-(1<<j);++i){ //利用状态转移方程f[i][j]=max(or min)(f[i][j-1],f[i+(1<<j-1)][j-1]); //即将区间(i,i+2^j)分成两个子区间(i,i+2^(j-1))和(i+2^(j-1),i+2^(j-1)+2^(j-1)); fmaxn[i][j]=max(fmaxn[i][j-1],fmaxn[i+(1<<(j-1))][j-1]); fminn[i][j]=min(fminn[i][j-1],fminn[i+(1<<(j-1))][j-1]); } } int ST_max(int l,int r){ int k=log(r-l+1)/log(2); //区间长度为r-l+1,化为指数形式以便进行划分子区间 //[l,r]区间被划为[l,l+2^k]和[l+1,l+1+2^k];这样划分的目的是防止有些区间被遗失 return max(fmaxn[l][k],fmaxn[r-(1<<k)+1][k]); } int ST_min(int l,int r){ int k=log(r-l+1)/log(2); return min(fminn[l][k],fminn[r-(1<<k)+1][k]); } int main() { scanf("%d%d",&n,&q); for(int i=0;i<n;++i) { scanf("%d",&a[i]); } ST_work(); int l,r; while(q--) { scanf("%d%d",&l,&r); l--;//与数组下标对齐 r--; printf("%d\n",ST_max(l,r)-ST_min(l,r)); } return 0; }
如有错误,欢迎指出!