uva11235 - Frequent values(RMQ)

看来传闻不差,数据结构的代码真的很长。。。

刘汝佳厚书P198。。。

查询优化,,,

以下摘自刘汝佳训练指南:

把整个数组进行游程编码,用value[],coun[]数组记录第i段的数值和出现次数,用num[p]、left[p]、right[p]记录位置p处所在段的编号和左右端点的位置,,,

所以最后只需对3个部分求最大值即可。

第一部分,左端,right[L]-L+1

第二部分,中间,RMQ(coun, num[L]+1, num[R]+1);

第三部分,右端,R-left[R]+1

另外要注意:如果L,R在同一段,则答案是R-L+1;

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define M 100005
#define INF 0x7fffffff
int a[M], value[M], coun[M], num[M], left[M], right[M], dp[M][20], len;
queue<int*>que;
void RMQ_init()
{
    for(int i = 1; i <= len; ++i) dp[i][0] = coun[i];
    for(int j = 1; (1<<j) <= len; ++j)
        for(int i = 1; i + (1<<j) <= len; ++i)
            dp[i][j] = max(dp[i][j-1], dp[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(dp[L][k], dp[R-(1<<k)+1][k]);
}
int main ()
{
    int n, q;
    int *p;
    while(scanf("%d",&n), n)
    {
        scanf("%d",&q);
        int cnt = 0;
        value[0] = INF;
        for(int i = 1; i <= n; ++i)
        {
             scanf("%d",&a[i]);
             if(a[i]!=value[cnt])
             {
                 while(!que.empty())
                 {
                     p = que.front();
                     que.pop();
                     *p = i-1;
                 }
                 ++cnt;
                 value[cnt] = a[i];
                 coun[cnt] = 1;
                 num[i] = cnt;
                 left[i] = i;
                 que.push(right+i);
             }
             else
             {
                 ++coun[cnt];
                 num[i] = cnt;
                 left[i] = left[i-1];
                 que.push(right+i);
             }
        }
        while(!que.empty())
        {
            p = que.front();
            que.pop();
            *p = n;
        }
        len = cnt;
        RMQ_init();
        while(q--)
        {
            int L, R, ans;
            scanf("%d %d",&L, &R);
            if(R<=right[L]&&L>=left[R]) { printf("%d\n", R-L+1); continue; }
            ans = max(right[L]-L+1, R-left[R]+1);
            ans = max(ans, RMQ( num[L]+1, num[R]-1));
            printf("%d\n",ans);
        }

    }
    return 0;
}


posted on 2013-07-31 21:17  Primo...  阅读(133)  评论(0编辑  收藏  举报