POJ3368/UVA-11235 Frequent values RMQ

这道题是紫书上198页的题,自己想我还真想不出来,比如游程编码和这么多数组。。

不过书上有一点我变了一下,按照自己的理解写的:p代表的不是p位置而是p位置对应的第i段,left和right数组都要对应变一下,我感觉这样比较好写。附上AC代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;
const ll MOD=1e9+7ll;

const int MAX=100005;
int n,q;
int a[MAX];
int r[MAX][20];
int val[MAX],coun[MAX];
int id[MAX],le[MAX],ri[MAX];

void initRMQ(int b[])
{
    memset(r,0,sizeof(r));
    for(int i=1;i<=n;i++)
        r[i][0]=b[i];
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            r[i][j]=max(r[i][j-1],r[i+(1<<(j-1))][j-1]);
}
int rmq(int x,int y)
{
    if(x>y)//注意要加
        return 0;
    int k=log(y-x+1.0)/log(2.0);
    return max(r[x][k],r[y-(1<<k)+1][k]);
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        if(n==0)
            break;
        scanf("%d",&q);
        memset(a,0,sizeof(a));
        memset(val,0,sizeof(val));
        memset(coun,0,sizeof(coun));
        memset(id,0,sizeof(id));
        memset(le,0,sizeof(le));
        memset(ri,0,sizeof(ri));
        scanf("%d",&a[1]);
        int pre=a[1];
        int seg=0;//第i段
        val[++seg]=pre;
        coun[seg]++;
        id[1]=seg;
        le[seg]=1;
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==pre)
            {
                id[i]=seg;
                coun[seg]++;
            }
            else
            {
                pre=a[i];
                ri[seg]=i-1;
                val[++seg]=pre;
                coun[seg]++;
                le[seg]=i;
                id[i]=seg;
            }
        }
        ri[seg]=n;
        /*for(int i=1;i<=seg;i++)
            cout<<"i="<<i<<" val="<<val[i]<<" coun="<<coun[i]<<" left="<<le[i]<<" right="<<ri[i]<<endl;
        cout<<endl;*/
        initRMQ(coun);
        int l,r;
        while(q--)
        {
            scanf("%d%d",&l,&r);
            if(id[l]==id[r])
            {
                printf("%d\n",r-l+1);
                continue;
            }
            int ans1=rmq(id[l]+1,id[r]-1);//注意范围
            int ans2=max(ri[id[l]]-l+1,r-le[id[r]]+1);
            printf("%d\n",max(ans1,ans2));
        }
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Cc_Sonia/article/details/82142570