标签:
题意:每次操作求区间[L,R]中最大值与最小值之差;
参考:http://blog.csdn.net/liang5630/article/details/7917702
思路:可以用线段树写,但ST算法求RMQ更方便;
dp[i][j]表示从第i个数开始到i+2^j中的最值;
在操作之前,预处理出每段区间的最值,采用二分区间求极值的思想,降低复杂度;
查询时,覆盖查询区间,长度R-L+1,对于dp中,j=log(R-L+1),在这段区间中二分区间求极值即可;
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m; int dpmax[300010][30]; int dpmin[300010][30]; int num[500010],mm[500010]; void init_rmq(){ mm[0]=-1; //用于计算log for(int i=1;i<=n;i++){ mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1]; dpmax[i][0]=num[i]; dpmin[i][0]=num[i]; } for(int j=1;j<=mm[n];j++) //枚举长度 for(int i=1;i+(1<<j)-1<=n;i++) //枚举起点 { dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]); dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]); } } int rmqmax(int x,int y){ int k=mm[y-x+1]; //覆盖查询区间所需的长度 return max(dpmax[x][k],dpmax[y-(1<<k)+1][k]); } int rmqmin(int x,int y){ int k=mm[y-x+1]; return min(dpmin[x][k],dpmin[y-(1<<k)+1][k]); } int main(){ int i,j,k,u,v; while(scanf("%d%d",&n,&m)!=EOF){ for(i=1;i<=n;i++) scanf("%d",&num[i]); init_rmq(); for(i=0;i<m;i++){ scanf("%d%d",&u,&v); int t1=rmqmax(u,v); int t2=rmqmin(u,v); printf("%d\n",t1-t2); } } return 0; }
poj 3264 Balanced Lineup(一维RMQ)
标签:
原文地址:http://www.cnblogs.com/dominatingdashuzhilin/p/4736970.html