UVA11235 Frequent values

链接的话是没有的,我是拿的洛咕的remote judge交的。

做之前一定要读好题面。

注意到是非减的。便由此可以,可以将连续的一段(or 一个)数字,压成一个数字。

然后再在上面处理问题。差不多类似分了个块吧。

然后这样的话,我们便只需要跑rmq就可以了。

对于块内,直接左右镶件。对于块见,使用数据结构维护,

然后因为是静态rmq,所以使用st表就比较优了。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using std::max;
const int maxn=101000;
int base[maxn];
int log[maxn];
int belong[maxn],id;
int l[maxn],r[maxn];
int st[maxn][22];
void init(int n)
{
    id=0;
    int now=-0x7fffffff; l[0]=0,id=0;base[n+1]=0x7fffffff;
    for(int i=1;i<=n+1;i++)
    {
        if(base[i]!=now)
        {
            r[id++]=i-1;
            l[id]=i;
            now=base[i];
        }
        belong[i]=id;
    }
    for(int i=1;i<id;i++)   st[i][0]=r[i]-l[i]+1;
    for(int i=1;i<=log[id-1];i++)
        for(int j=1;j+(1<<i)-1<id;j++)
            st[j][i]=max(st[j][i-1],st[j+(1<<i-1)][i-1]);
    return ;
}
int check(int L,int R)
{
    if(L>R) return 0;
    if(L==R)    return r[L]-l[R]+1;
    int len=log[R-L+1];
    return max(st[L][len],st[R-(1<<len)+1][len]);
}
int main()
{
    for(int i=2;i<maxn;i++)   log[i]=log[i>>1]+1;
    int n,q;
    scanf("%d",&n);
    while(n)
    {
        scanf("%d",&q);
        for(int i=1;i<=n;i++)   scanf("%d",&base[i]);
        init(n);
        int a,b;
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&a,&b);
            if(belong[a]==belong[b])
                printf("%d\n",b-a+1);
            else
            {
                int ans=check(belong[a]+1,belong[b]-1);
                ans=max(ans,max(r[belong[a]]-a+1,b-l[belong[b]]+1));
                printf("%d\n",ans);
            }
        }
        scanf("%d",&n);
    }
}

猜你喜欢

转载自www.cnblogs.com/Lance1ot/p/9895174.html
今日推荐