您的位置:首页 > 产品设计 > UI/UE

Poj 3368 Frequent values

2015-03-20 22:37 239 查看
题意:

给定不降序列,询问区间中最多重复的次数。

题解:

多次查询不变序列的最值,很容易考虑rmq去处理;

但是如果直接处理的话,显然最多相同数字个数不满足倍增性质;

所以我们要做一些其他预处理, 比如用线段树解决(笑);

或者考虑,rmq[i][j]表示从i到i+2^j这段区间中,某数左侧与其相同的数字最大总数;

这个,是满足倍增性质的呢, 我们把这个预处理出来,可是询问时rmq的值可能会的在左侧超出询问区间;

所以我们需要在[l,r]里面找到一个满足rmq的起始位置t,从而在[t,r]中找到的最大总数是在[l,r]区间中的;

如何找到t,就可以利用并查集的思想,维护一个f[i],为a[i]这个数字在左侧的端点;

于是找t的时候我们找到的第一个f[i]>=l的就是t; 很显然的,f[i]满足单调递增,可以二分解决这个查找;

然后我们取rmq最大值和t-l取最大值就是答案了;

rmq+并查集预处理+二分;

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define N 100001
using namespace std;
int f
,rmq
[20];
int main()
{
    int n,m,i,j,k,t,l,r;
    while(scanf("%d",&n)&&n)
    {
        memset(f,0,sizeof(f));
        memset(rmq,0,sizeof(rmq));
        scanf("%d%d",&m,&t);
        f[1]=1,rmq[1][0]=1;
        for(i=2;i<=n;i++)
        {
            scanf("%d",&j);
            if(j==t)
            {
                f[i]=f[i-1];
            }
            else
            {
                f[i]=i;
            }
            t=j;
            rmq[i][0]=i-f[i]+1;
        }
        for(k=1;(1<<k)<=n;k++)
        {
            for(i=1;i<=n-(1<<k)+1;i++)
            {
                rmq[i][k]=max(rmq[i][k-1],rmq[i+(1<<(k-1))][k-1]);
            }
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&l,&r);
            if(l>r) swap(l,r);
            if(f[r]<l)
            {
                printf("%d\n",r-l+1);
                continue;
            }
            t=lower_bound(f+l,f+r,l)-f;
            k=log(r-t+1.0)/log(2.0);
            printf("%d\n",max(t-l,max(rmq[t][k],rmq[r-(1<<k)+1][k])));
        }
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: