题目链接:http://poj.org/problem?id=3264
题意:求出一个给定的区间的最大差值。
很典型的RMQ问题,也可以用线段树做。
(Ps:不明白为什么poj上c++提交第一份代码会CE,log函数不是在math头文件里么?G++可以交)
①RMQ(3750ms):
<pre name="code" class="cpp">#include<iostream> #include<cstdio> #include<cstring> #include<math.h> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=50005; int n,q; int f[maxn]; int minNum[maxn][32],maxNum[maxn][32]; //dp[i, j]表示从第i个数起连续2^j个数中的最大值; void RMQ(){ for(int i=1;i<=n;i++) minNum[i][0]=maxNum[i][0]=f[i]; for(int j=1;j<=20;j++){ for(int i=1;i<=n;i++){ if(i+(1<<j)-1<=n){ minNum[i][j]=min(minNum[i][j-1],minNum[i+(1<<(j-1))][j-1]); maxNum[i][j]=max(maxNum[i][j-1],maxNum[i+(1<<(j-1))][j-1]); } } } } int main() { #ifndef ONLINE_JUDGE freopen("test.in","r",stdin); freopen("test.out","w",stdout); #endif while(~scanf("%d%d",&n,&q)){ for(int i=1;i<=n;i++) scanf("%d",&f[i]); RMQ(); int a,b; while(q--){ scanf("%d%d",&a,&b); int k=(int)log2(b-a+1); int intervalMin=min(minNum[a][k],minNum[b-(1<<k)+1][k]); int intervalMax=max(maxNum[a][k],maxNum[b-(1<<k)+1][k]); printf("%d\n",intervalMax-intervalMin); } } return 0; }
②线段树(1735ms):
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=50005; int n,q; int minNum,maxNum; struct segmentTree{ int l; int r; int min; int max; }node[3*maxn]; void PushUp(int rt){ node[rt].min=min(node[rt<<1].min,node[rt<<1|1].min); node[rt].max=max(node[rt<<1].max,node[rt<<1|1].max); } void build(int rt,int l,int r){ node[rt].l=l; node[rt].r=r; if(l==r) return ; int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void Update(int rt,int L,int R,int pos,int val){ if(L==pos&&R==pos){ node[rt].min=val; node[rt].max=val; return ; } int mid=(L+R)>>1; if(pos<=mid) Update(rt<<1,L,mid,pos,val); if(pos>mid) Update(rt<<1|1,mid+1,R,pos,val); PushUp(rt); } void Query(int rt,int L,int R,int l,int r){ if(L==l&&R==r){ minNum=min(minNum,node[rt].min); maxNum=max(maxNum,node[rt].max); return ; } int mid=(L+R)>>1; if(l>mid) Query(rt<<1|1,mid+1,R,l,r); else if(r<=mid) Query(rt<<1,L,mid,l,r); else{ Query(rt<<1,L,mid,l,mid); Query(rt<<1|1,mid+1,R,mid+1,r); } } int main() { #ifndef ONLINE_JUDGE freopen("test.in","r",stdin); freopen("test.out","w",stdout); #endif while(~scanf("%d%d",&n,&q)){ build(1,1,n); int x; for(int i=1;i<=n;i++){ scanf("%d",&x); Update(1,1,n,i,x); } int a,b; while(q--){ scanf("%d%d",&a,&b); minNum=INF,maxNum=-INF; Query(1,1,n,a,b); printf("%d\n",maxNum-minNum); } } return 0; }