pku 3264 http://poj.org/problem?id=3264
题意:
给定n个奶牛的高度,求区间[s,e]中最高与最低高度的差值。
rmq模板题目:
求出最高最低然后求差。
注意这里f[i][j]表示从j开始的2^i次方个数的最值。
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #define maxn 50007 #define N 22 using namespace std; int fMin[N][maxn],fMax[N][maxn]; int pow2[N],a[maxn]; void init_rmq(int len) { int i,j; for (i = 0; i < N; ++i) pow2[i] = 1<<i; for (i = 1; i <= len; ++i) fMin[0][i] = fMax[0][i] = a[i]; for (i = 1; pow2[i] <= len; ++i)//pow2[i]表示长度一定小于总长度 { for (j = 1; j + pow2[i - 1] <= len; ++j)//j + pow2[i - 1]表示右边的起点一定要小于最右边的坐标 { fMax[i][j] = max(fMax[i - 1][j],fMax[i - 1][j + pow2[i - 1]]); fMin[i][j] = min(fMin[i - 1][j],fMin[i - 1][j + pow2[i - 1]]); } } } int rmq(int s,int e) { int k = log(1.0*(e -s + 1))/log(2.0); int Max = max(fMax[k][s],fMax[k][e - pow2[k] +1]); int Min = min(fMin[k][s],fMin[k][e - pow2[k] +1]); return Max - Min; } int main() { //freopen("d.txt","r",stdin); int n,q,i; int s,e; scanf("%d%d",&n,&q); for (i = 1; i <= n; ++i) scanf("%d",&a[i]); init_rmq(n); while (q--) { scanf("%d%d",&s,&e); printf("%d\n",rmq(s,e)); } return 0; }
pku Frequent values http://poj.org/problem?id=3368
题意:
给定长度为n的不降序列,求询问区间[s,e]内出现频率最高的频率;
思路:
本题可用线段树的区间合并来做:http://www.cnblogs.com/E-star/archive/2012/07/26/2609475.html
rmq做法,首先将其离散化相同的点映射到一个点上,并记录该点能够达到的最左端点最有端点;
分三种情况讨论[s,e]
hash[i]位i离散化后对应的新序号,R[hash[i]]表示i离散化后的点能够到达的最右端,L[hash[i]]表示i离散化后的点能够到达的最左端,
1:如果s与e对应的离散化后的点为同一点则频率为 e - s + 1;(1,1,1,1)
2:如果s与e所对应的离散化后的点相差1则频率为 Li = R[hash[l]] - l + 1; Ri = r - L[hash[r]] + 1; max(Li,Ri); (1 1 3 3)
3:如果s与e所对应的离散化后的点相差大于1则频率为
Li = R[hash[l]] - l + 1;
Ri = r - L[hash[r]] + 1;
Li = max(Li,Ri);
Ri = rmq(hash[l] + 1,hash[r] - 1);
max(Li,Ri);
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #define maxn 100007 using namespace std; int hash[maxn],L[maxn],R[maxn]; int a[maxn],f[maxn][22],pow2[22]; void init_rmq(int len) { int i,j; for (i = 0; i < 22; ++i) pow2[i] = 1<<i; for (j = 1; pow2[j] <= len; ++j) { for (i = 1; i + pow2[j] <= len; ++i) f[i][j] = max(f[i][j - 1],f[i + pow2[j - 1]][j - 1]); } } int rmq(int s,int e) { int k = log(1.0*(e - s + 1))/log(2.0); return max(f[s][k],f[e - pow2[k] + 1][k]); } void solve(int l,int r) { int Li,Ri; if (hash[l] == hash[r]) { printf("%d\n",r - l + 1); } else if (hash[l] + 1 == hash[r]) { Li = R[hash[l]] - l + 1; Ri = r - L[hash[r]] + 1; printf("%d\n",max(Li,Ri)); } else { Li = R[hash[l]] - l + 1; Ri = r - L[hash[r]] + 1; Li = max(Li,Ri); Ri = rmq(hash[l] + 1,hash[r] - 1); printf("%d\n",max(Li,Ri)); } } int main() { //freopen("d.txt","r",stdin); int n,q,i; while (~scanf("%d",&n)) { if (!n) break; scanf("%d",&q); for (i = 1; i <= n; ++i) scanf("%d",&a[i]); hash[1] = 1; L[1] = 1; R[1] = 1; int cnt = 1; for (i = 2; i <= n; ++i) { if (a[i] == a[i - 1]) { hash[i] = hash[i - 1]; R[hash[i]] = i; } else { f[cnt][0] = R[cnt] - L[cnt] + 1;//直接对f初始化了。 hash[i] = ++cnt; L[cnt] = i; R[cnt] = i; } } f[cnt][0] = R[cnt] - L[cnt] + 1; init_rmq(cnt); int s,e; while (q--) { scanf("%d%d",&s,&e); solve(s,e); } } return 0; }