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

博客介绍了如何使用线段树解决POJ 3368问题,该问题要求找出有序数组中指定区间内连续出现次数最多的元素的最长连续次数。博客提供了题意解析、线段树的实现细节以及相应的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

#include<iostream>
#include<algorithm>
#include<stdio.h>
#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<x||r<l) return 0;
    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));
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值