Poj 3368 Frequent values

Posted 一入OI深似海

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Poj 3368 Frequent values相关的知识,希望对你有一定的参考价值。

/*
线段树区间合并
维护几个信息 到时候乱搞一下就好了
开始T了 有一种情况可以不用递归 直接算出来 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
#define lc (k<<1)
#define rc (k<<1)+1
#define mid ((l+r)>>1)
using namespace std;
int n,m,a[maxn],ls[maxn*4],rs[maxn*4],ln[maxn*4],rn[maxn*4],s[maxn*4];
int init(){
    int x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
void Build(int k,int l,int r){
    if(l!=r){
        Build(lc,l,mid);
        Build(rc,mid+1,r);
        s[k]=max(s[lc],s[rc]);
        if(rn[lc]==ln[rc])
            s[k]=max(s[k],rs[lc]+ls[rc]);
        ln[k]=ln[lc];rn[k]=rn[rc];
        ls[k]=ls[lc];rs[k]=rs[rc];
        if(ls[lc]==mid-l+1&&rn[lc]==ln[rc])
            ls[k]=max(ls[k],ls[lc]+ls[rc]);
        if(rs[rc]==r-mid&&rn[lc]==ln[rc])
            rs[k]=max(rs[k],rs[rc]+rs[lc]);
    }
    else{
        ls[k]=rs[k]=1;ln[k]=rn[k]=a[l];s[k]=1;
    }
}
int Query(int k,int l,int r,int x,int y){
    if(x<=l&&y>=r)return s[k];
    int ret=0,L,R;
    if(y<=mid)return Query(lc,l,mid,x,y);
    else if(x>mid)return Query(rc,mid+1,r,x,y);
    else{
        if(rn[lc]==ln[rc]){
            L=max(mid-rs[lc]+1,x);
            R=min(mid+ls[rc],y);
            ret=mid-L+1+R-mid;
        }
            //ret=Query(lc,l,mid,max(mid-rs[lc]+1,x),mid)
            //+Query(rc,mid+1,r,mid+1,min(mid+ls[rc],y));可以只结算出来 QAQ T了好几遍 
        ret=max(ret,Query(lc,l,mid,x,y));
        ret=max(ret,Query(rc,mid+1,r,x,y));
    }
    return ret;
}
int main()
{
    while(1){
        n=init();if(n==0)break;
        m=init();
        for(int i=1;i<=n;i++)a[i]=init();
        Build(1,1,n);
        while(m--){
            int L,R;
            L=init();R=init();
            printf("%d\n",Query(1,1,n,L,R));
        }
    }
    return 0;
}
/*
ST表做法 比较巧妙 时间差不多 空间大一些 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
using namespace std;
int n,m,a[maxn],c[maxn],f[maxn][25],lst[maxn],p[maxn];
int init(){
    int x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
void Clear(){
    memset(c,0,sizeof(c));
    memset(f,0,sizeof(f));
    memset(lst,0,sizeof(lst));
}
void Get_p(){
    for(int i=1;i<=maxn-10;i++)
        for(int j=0;j<=20;j++)
            if((1<<j)>i){
                p[i]=j-1;break;
            }
}
void Get_ST(){
    for(int i=1;i<=n;i++)f[i][0]=c[i];
    for(int j=1;j<=20;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]); 
}
int Query(int l,int r){
    if(l>r)return 0;
    int k=p[r-l+1];
    return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
    Get_p();
    while(1){
        n=init();if(n==0)break;m=init();
        Clear();
        for(int i=1;i<=n;i++)a[i]=init();
        for(int i=1;i<=n;i++)
            if(a[i]==a[i-1])c[i]=c[i-1]+1;
            else c[i]++;
        for(int i=n;i>=1;i--)
            if(a[i]==a[i+1])lst[i]=lst[i+1];
            else lst[i]=i;
        Get_ST();
        while(m--){
            int L,R,mxx=0,mx=0;
            L=init();R=init();
            mxx=Query(lst[L]+1,R);
            mx=min(lst[L],R)-L+1;
            printf("%d\n",max(mxx,mx));
        }
    }
    return 0;
}

 

以上是关于Poj 3368 Frequent values的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3368 Frequent values (ST表)

poj3368 Frequent values

POJ 3368 Frequent values(线段树区间合并)

POJ3368Frequent values[RMQ 游程编码]

Poj 3368 Frequent values

POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)