-
A - Balanced Lineup
- POJ - 3264
- 题意:查询区间最大最小值之差
- 思路:rmq查询即可,说一下对rmq的理解dp数组 i,j 表示的是从给定序列的第i个位置起向后到i+(1<<j)之间的最值
- 状态转移方程为dp[i][j]=max或min(dp[i][j-1],dp[i+(1<<(j-1))][j-1])意思是把第i个位置起向后到i+(1<<j)这段区间分为两段
- 一段为i—>i+1<<(j-1)另一段 i+1<<(j-1)—>i+1<<(j-1)+1<<(j-1)后面这个一化简就是 i+1<<(j-1)—>i+1<<j。
- 查询操作时原则为可以覆盖不要漏掉所以先求一下被查询的区间长度为2的几次方 代码为int k=log(r-l+1)/log(2);
- 然后 返回min(dpmin[l][k],dpmin[r-(1<<k)+1][k])这样就保证区间内的点都不会漏掉。
#include<iostream> #include<cstring> #include<cmath> #include<stdio.h> using namespace std; #define maxn 90000 #define maxm 30 int dpmin[maxn][maxm]; int dpmax[maxn][maxm]; int a[maxn],n,q,l,r; void rmqinit() { for(int j=1; (1<<j)<=n; j++) for(int i=1; i+(1<<j)<n+2; i++) { dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]); dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]); } } int rmqmin(int l,int r) { int k=log(r-l+1)/log(2); return min(dpmin[l][k],dpmin[r-(1<<k)+1][k]); } int rmqmax(int l,int r) { int k=log(r-l+1)/log(2); return max(dpmax[l][k],dpmax[r-(1<<k)+1][k]); } int main() { scanf("%d%d",&n,&q); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); dpmin[i][0]=dpmax[i][0]=a[i]; } rmqinit(); while(q--) { scanf("%d%d",&l,&r); printf("%d\n",rmqmax(l,r)-rmqmin(l,r)); } return 0; }
A - Balanced Lineup-RMQ模板
最新推荐文章于 2022-03-26 21:08:54 发布