【poj 3368】Frequent values 题意&题解&代码(C++)

题目链接:
http://poj.org/problem?id=3368
题意:
给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之间连续出现次数最多的次数(保证给出n个数按升序排列)。
题解:
线段树存三个信息,L,M,R,分别表示左端点开始的最长连续子段的长度,整段区间最长连续子段长度,从右端点开始的最长连续子段的长度,具体查询与维护方法看代码:
代码:

#include
#include
#include
#define lson (id*2)
#define rson (id*2+1)
#define maxn (400005)
using namespace std;
int n,m,a[100005],L[maxn],R[maxn],M[maxn];
void pushup(int id,int l,int r)
{
    int mid=(l+r)/2;
    if (a[mid]==a[mid+1])
    M[id]=max(max(M[lson],M[rson]),R[lson]+L[rson]);
    else    M[id]=max(M[lson],M[rson]);
    if (L[lson]==mid-l+1 && a[mid]==a[mid+1])   L[id]=L[lson]+L[rson];
    else L[id]=L[lson];
    if (R[rson]==r-mid && a[mid]==a[mid+1]) R[id]=R[lson]+R[rson];
    else R[id]=R[rson];
}
void build(int id,int l,int r)
{
    if (l>r) return ;
    if (l==r) 
    {
        L[id]=1;R[id]=1;M[id]=1;
        return ;
    }
    int mid=(l+r)/2;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(id,l,r);
}
int query(int id,int l,int r,int x,int y)
{
    //if(l>y||r
    if (x<=l && y>=r) return M[id];
    int mid=(l+r)/2;
    if (y<=mid) return query(lson,l,mid,x,y);
    if (x>=mid+1) return query(rson,mid+1,r,x,y);
    int m1,m2,m3;
    if (a[mid]==a[mid+1])
    m1=min(R[lson],mid-x+1)+min(L[rson],y-mid);
    m2=query(lson,l,mid,x,y);
    m3=query(rson,mid+1,r,x,y);
    return max(max(m1,m2),m3);
    return 0;
}
int aa,bb;
int main()
{
    while(scanf("%d",&n))
    {
        if (n==0) return 0;
        scanf("%d",&m);
        for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        build(1,1,n);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&aa,&bb);
            printf("%d\n",query(1,1,n,aa,bb));
        }
    }

}

你可能感兴趣的:(oi之路,poj)