uva11235(RMQ问题)

来源:互联网 发布:cad制图软件下载 编辑:程序博客网 时间:2024/05/01 22:46

   题目的意思是:有一个有序的数组,然后每次给出数组的两个端点L,R,要求出数组区间[L,R]里面出现最多的数字。

   题目的解法:运用RMQ的思想求解即可,在求解之前需要转化一下模型,我们把这个数组可以转化为对于数字p,记录它的左端点位置nL[p],右端点位置nR[p],个数nV[p],对于每一次访问实际我们可以分三块来进行求解:首先是左端点num[L]的数字个数等于nR[num[L]] - L + 1,右端点的num[R]的数字个数等于R - nL[num[R]] + 1,然后中间的数字结果就用RMQ进行求解。

   RMQ求解的主要代码块:  

  for(int i = 0; i < cN; i ++) A[i][0] = nV[num2[i]];  for(int j = 1; (1 << j) <= cN; j ++){        for(int i = 0; i + (1 << j) <= cN; i ++){A[i][j] = max(A[i][j-1], A[i+(1 << (j - 1))][j - 1]);    }  }
  <pre name="code" class="cpp">  ans = nR[num1[L]] - L + 1;  ans = max(R - nL[num1[R]] + 1, ans);  L = p[num1[L]] + 1, R = p[num1[R]] - 1;  if(L <= R){    int k = 0;    while((1 << (k + 1)) <= R - L + 1) k ++;    ans = max(ans, A[L][k]);    ans = max(ans, A[R + 1 - (1 << k)][k]);  }

    

    

#include "stdio.h"#include "string.h"#include "math.h"#include <string>#include <queue>#include <stack>#include <vector>#include <map>#include <algorithm>#include <iostream>using namespace std;#define MAXM 1#define MAXN 1#define max(a,b) a > b ? a : b#define min(a,b) a < b ? a : b#define Mem(a,b) memset(a,b,sizeof(a))int Mod = 1000000007;double pi = acos(-1.0);double eps = 1e-6;typedef struct{int f,t,w,next;}Edge;Edge edge[MAXM];int head[MAXN];int kNum;typedef long long LL;void addEdge(int f, int t, int w){edge[kNum].f = f;edge[kNum].t = t;edge[kNum].w = w;edge[kNum].next = head[f];head[f] = kNum ++;}map<int,int> nL, nR, nV;map<int,int> p;int n, cN, q;int A[100005][20];int num1[100005];int num2[100005];void solve(){cin>>q;for(int i = 0; i < n; i ++){scanf("%d", &num1[i]);}nL.clear(), nR.clear(), nV.clear();p.clear(), cN = 0;Mem(A, 0);int flag = false, pre = -1;nL[num1[0]] = 1;p[num1[0]] = cN ++;num2[0] = num1[0];for(int i = 1; i < n; i ++){if(num1[i] != num1[i-1]){nR[num1[i-1]] = i - 1;nV[num1[i-1]] = nR[num1[i-1]] - nL[num1[i-1]] + 1;//pre = num1[i];num2[cN] = num1[i];nL[num1[i]] = i;p[num1[i]] = cN ++;//flag = true;}}nR[num1[n-1]] = n - 1;nV[num1[n-1]] = nR[num1[n-1]] - nL[num1[n-1]] + 1;for(int i = 0; i < cN; i ++) A[i][0] = nV[num2[i]];for(int j = 1; (1 << j) <= cN; j ++){for(int i = 0; i + (1 << j) <= cN; i ++){A[i][j] = max(A[i][j-1], A[i+(1 << (j - 1))][j - 1]);}}int L, R, ans;for(int i = 0; i < q; i ++){scanf("%d %d",&L, &R);L -= 1, R -= 1;if(num1[L] == num1[R]){printf("%d\n", R - L + 1);}else{ans = nR[num1[L]] - L + 1;ans = max(R - nL[num1[R]] + 1, ans);L = p[num1[L]] + 1, R = p[num1[R]] - 1;if(L <= R){int k = 0;while((1 << (k + 1)) <= R - L + 1) k ++;ans = max(ans, A[L][k]);ans = max(ans, A[R + 1 - (1 << k)][k]);}printf("%d\n", ans);}}}int main(){//freopen("d:\\test.txt", "r", stdin);while(cin>>n){if(n == 0) break;solve();}return 0;}

0 0
原创粉丝点击