【RMQ】 UVA 11235 Frequent values

大白例题

题意:给出一个不递减序列 

 再给出多个询问 l  r 

输出 l - r 区间内 出现最多的数的次数

同段表示值相同的一段

计算每个位置的 left   :同段中最左边位置

right  :同段中最右边位置

num  :第几段

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cmath>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <map>
#define cler(arr, val)    memset(arr, val, sizeof(arr))
typedef long long  LL;
const int MAXN = 240000;
const int MAXM = 140000;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
int dp[MAXN][22],val[MAXN],c[MAXN];
int A[MAXN*2];
int n,m,num;
struct node
{
    int left,right,num;
}p[MAXN];
void RMQ_init()
{
    for(int i=0;i<num;i++)
        dp[i][0]=c[i];
    for(int i=1;(1<<i)<=num;i++)
        for(int j=0;j+(1<<i)-1<num;j++)
            dp[j][i]=max(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);
}
int RMQ(int l,int r)
{
    int k=(int)(log(double(r-l+1))/log((double)2));
    return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    while(cin>>n,n)
    {
        cin>>m;
        cler(c,0);
        num=-1;
        int x;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&A[i]);
            if(i==0||A[i-1]!=A[i])
            {
                num++;
                val[num]=A[i];
                x=i;
            }
            c[num]++;
            p[i].num=num;
            p[i].left=x;
        }
        num++;
        for(int i=0;i<n;i++)
        {
            p[i].right=p[i].left+c[p[i].num]-1;
        }
        RMQ_init();
        int a,b;
        for(int i=0;i<m;i++)
        {
            scanf("%d %d",&a,&b);
            a--,b--;
            if(p[a].num==p[b].num)
            {
                printf("%d\n",b-a+1);
                continue;
            }
           // printf("p[a].right-a+1:%d\n",p[a].right-a+1);
           // printf("b-p[b].left+1 :%d\n",b-p[b].left+1);
            int ans=max(p[a].right-a+1,b-p[b].left+1);
            if(p[a].num+1<=p[b].num-1)
                ans=max(ans,RMQ(p[a].num+1,p[b].num-1));
            printf("%d\n",ans);
        }
    }
    return 0;
}


posted @ 2014-11-08 09:22  kewowlo  阅读(124)  评论(0编辑  收藏  举报