/* RMQ问题 ----------------------------------------------------------------------------------------------- 用数组: cnt[i]:第i段中数的个数(每一段是指所有数都同的一段数)(在这里该数组相当于RMQ问题中的A[]数组) num[i]:位置i所在段的编号 left1[i]:位置i左端点的位置 right1[i]:位置i右端点的位置 ---------------------------------------------------------------------------------------------- right1[L]-L+1:从L到该段末尾元素的个数 R-left[R]+1:从该段开始元素到R处的元素个数 RMQ(num[L]+1, num[R]-1):从num[L]+1段到num[R]-1段中的最大cnt; 最后的结果为以上三个数的最大值: ---------------------------------------------------------------------------------------------- 若:num[L] == num[R](即:L和R在同一段中),结果为R-L+1; ---------------------------------------------------------------------------------------------- RMQ: void RMQ_init()预处理 { int n = size; for(int i=0; i<n; i++) d[i][0] = cnt[i]; for(int j=1; (1<<j) <= n; j++) { for(int i=0; i + (1<<j) - 1 < n; i++) { d[i][j] = max(d[i][j-1], d[i + (1<<(j-1))][j-1]); } } } int RMQ(int L, int R)查询 { if(L > R) return 0; int k = 0; while((1<<(k+1)) <= R-L+1) k++; return max(d[L][k], d[R-(1<<k)+1][k]); } -------------------------------------------------------------------------------------- cnt数组,left1数组,right1数组的构建: int x,p = 100000000;----------------------------P要大于x的取值范围 int ct = -1;------------------------------------输入数据的段数 int _left;--------------------------------------当前段的左端点 for(int i=0; i<n; i++) { scanf("%d",&x); if(x == p) { cnt[ct]++;------------------------------如果输入的数和前一个数同,该段个数+1 num[i] = ct;----------------------------不断更新位置i所在的段 left1[i] = _left;-----------------------更左端点 } else { if(ct >= 0) { for(int j=_left; j<=i-1; j++)-------更新右端点 right1[j] = i-1; } ct++; _left = i; num[i] = ct; left1[i] = _left; cnt[ct] = 1; p = x; } } for(int i=_left; i<n; i++) right1[i] = n-1; size = ct+1; ------------------------------------------------------------------------------ */ #include <iostream> #include <cstdio> #include <climits> #include <cstring> using namespace std; const int N = 100010; int n,q; int cnt[N],num[N],left1[N],right1[N]; int a[N]; int size; int d[N][30]; void RMQ_init() { int n = size; for(int i=0; i<n; i++) d[i][0] = cnt[i]; for(int j=1; (1<<j) <= n; j++) { for(int i=0; i + (1<<j) - 1 < n; i++) { d[i][j] = max(d[i][j-1], d[i + (1<<(j-1))][j-1]); } } } int RMQ(int L, int R) { if(L > R) return 0; int k = 0; while((1<<(k+1)) <= R-L+1) k++; return max(d[L][k], d[R-(1<<k)+1][k]); } int main() { //freopen("input.txt","r",stdin); while(scanf("%d%d",&n,&q) != EOF && n) { memset(cnt, 0, sizeof(cnt)); memset(left1, 0, sizeof(left1)); memset(right1, 0, sizeof(right1)); memset(d, 0, sizeof(d)); int x,p = 100000000; int ct = -1; int _left; for(int i=0; i<n; i++) { scanf("%d",&x); if(x == p) { cnt[ct]++; num[i] = ct; left1[i] = _left; } else { if(ct >= 0) { for(int j=_left; j<=i-1; j++) right1[j] = i-1; } ct++; _left = i; num[i] = ct; left1[i] = _left; cnt[ct] = 1; p = x; } } for(int i=_left; i<n; i++) right1[i] = n-1; size = ct+1; RMQ_init(); while(q--) { int L,R; scanf("%d%d",&L,&R); L--; R--; int t1 = right1[L]-L+1; int t2 = RMQ(num[L]+1, num[R]-1); int t3 = R-left1[R]+1; if(num[L] == num[R]) printf("%d\n",R-L+1); else printf("%d\n",max(t1, max(t2, t3))); } } return 0; }
【RMQ问题】uva11235Frequent values,布布扣,bubuko.com
【RMQ问题】uva11235Frequent values
原文:http://blog.csdn.net/u013147615/article/details/38409207