解决方案一:用线段树解决,因为查询的是某区间的最值
时间1396 | 空间 5304 代码长度75 |
#include <iostream> #include <algorithm> #include <cstdio> using namespace std; struct node { int l,r,min,max; }; const int N=100005; int num[N]; #define L(x) (x<<1) #define R(x) ((x<<1)+1) #define M(x,y) ((x+y)>>1) node tree[4*N]; int big,small; //建立线段树,由于是某个区间并未涉及到单个点,我建立的是叶子节点区间长度为1,而不是到单个点的线段树 void build(int t,int l,int r) { tree[t].l=l; tree[t].r=r; if(l+1==r) { if(num[l]>num[r]){tree[t].min=num[r];tree[t].max=num[l];} else {tree[t].min=num[l];tree[t].max=num[r];} return; } int mid=M(l,r); build(L(t),l,mid); build(R(t),mid,r); tree[t].max=max(tree[L(t)].max,tree[R(t)].max); tree[t].min=min(tree[L(t)].min,tree[R(t)].min); } //查询操作很简单,看看这个区间的最大最小值就行了 void query(int t,int l,int r) { if(tree[t].l>=l && tree[t].r<=r) { if(tree[t].max>big)big=tree[t].max; if(tree[t].min<small)small=tree[t].min; return; } int mid=M(tree[t].l,tree[t].r); if(r<=mid)query(L(t),l,r); else if(l>=mid)query(R(t),l,r); else { query(L(t),l,mid); query(R(t),mid,r); } } int main() { int i,n,q; scanf("%d%d",&n,&q); for(i=1;i<=n;i++)scanf("%d",num+i); build(1,1,n); int a,b; while(q--) { scanf("%d%d",&a,&b); big=-1,small=100000005; //考虑问题要全面,当a==b时,线段树是不适应的,因为我建立的线段树是[a,b],[b,c],应该列出来单独考虑,在这个地方两次没提交成功 if(a==b)printf("0\n");, else { query(1,a,b); printf("%d\n",big-small); } } system("pause"); return 0; }
解决方案二:rmq的st算法即sparse table
时间 904 | 空间:15852 |
#include <iostream> #include <cmath> #include <algorithm> #include <cstdio> using namespace std; const int N=100000; int stmax[N][20],stmin[N][20],d[20]; void init(int n) { int i,j; d[0]=1; for(i=1;i<=20;i++)d[i]=d[i-1]<<1; for(i=1;i<=n;i++){ scanf("%d",&stmax[i][0]); stmin[i][0]=stmax[i][0]; } int len = int(log(n*1.0)/log(2.0)); for(j=1;j<=len;j++) for(i=1;i<=n;i++) if(i+d[j]-1<=n) { stmax[i][j]=max(stmax[i][j-1],stmax[i+d[j-1]][j-1]); stmin[i][j]=min(stmin[i][j-1],stmin[i+d[j-1]][j-1]); } } void rmq(int q) // { int x,y,len; while(q--) { scanf("%d%d",&x,&y); len=int(log(y-x+1.0)/log(2.0)); printf("%d\n",max(stmax[x][len],stmax[y-d[len]+1][len])); printf("%d\n",min(stmin[x][len],stmin[y-d[len]+1][len])); } } int main(){ int n, q; scanf("%d%d",&n,&q); init(n); rmq(q); system("pause"); return 0; }
15852 代码长度:45行 |