1. 程式人生 > >UVA11235 Frequent values

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);
    }
}