您的位置:首页 > 其它

poj 3368

2016-07-21 18:09 253 查看

Frequent values

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 13771 Accepted: 5045
Description

You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1
≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integers ai , ... , aj.

Input

The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , ... , an (-100000
≤ ai ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two
integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the 

query.

The last test case is followed by a line containing a single 0.

Output

For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.

Sample Input
10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0

Sample Output
1
4
3

Source

Ulm Local 2007

题目连接:http://poj.org/problem?id=3368

解法(网上也有其他解法,但是似乎要设好几个数组,感觉挺麻烦也挺难理解的,以下是我的解法)

ac代码

#include <iostream>

#include <cmath>

#include <cstdio>

using namespace std;

int a[1000005],b[1000005];

int f[1000005][20];

int q,n,h,t,r,p,y,s,i,j;

void rmq_init() //建立: dp(i,j) = min{dp(i,j-1),dp(i+2^(j-1),j-1)   O(nlogn)

{

    for(int i=1; i<=n; i++)

        f[i][0] = a[i];

    int k=floor(log((double)n)/log(2.0)); //C/C++取整函数ceil()大,floor()小

    for(int j=1; j<=k; j++)

        for(int i=n; i>=1; i--)

        {

            if(i+(1<<(j-1))<=n) //f(i,j) = min{f(i,j-1),f(i+2^(j-1),j-1)

                f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);

        }

}

int rmq(int i,int j)  //查询:返回区间[i,j]的最小值     O(1)

{

    int k = floor(log((double)(j-i+1))/log(2.0));

    return max(f[i][k],f[j-(1<<k)+1][k]);

}                                                                                                       //这两部分函数都是st表的套路,不详细说明

int main()

{

    while(scanf("%d",&n)!=EOF&&n!=0)

    {

        scanf("%d",&q);

        for(int i=1; i<=n; i++)

            scanf("%d",&b[i]);                                                 //b【n】存储输入数组

        a[1]=1;

        for(i=2; i<=n; i++)

        {

            if(b[i]==b[i-1])

                a[i]=a[i-1]+1;

            else

                a[i]=1;

        }                                                                                  //a【n】用记录相同数字出现的次数   例 -1 -1 1 1 2 2 对应1 2 1 2 1 2                 

        rmq_init();

        for(int i=1; i<=q; i++)

        {

            scanf("%d%d",&h,&t);  

            for(j=h,y=0; j<=t; j++)                                            //现在的问题就在于对它分割数组的位置的讨论,其实只要就是头和尾

            {

                if(a[j]!=1)

                    y++;                                                                 //例如如果h和t截出的数组对应的a是 3 4 1 2 3 1 2

                else                                                                       y记录开头不合适的部分(3、4)y=2

                    break;

            }

            if(a[t]-a[h]!=t-h)                                                  //   同理要对后尾不合适的部分进行计数 这个情况有点多

            {

                if(a[t]==1)

                {

                    s=0;

                    p=rmq(h+y,t-s);                                      //去掉头和尾不合适的数后,就可以通过rmq找到最大值 在拿头尾计数和最大值比较  输出最后的最大值

                    r=max(p,y);

                    printf("%d\n",max(r,s));                           

                }

                else if(a[t]!=1)

                {

                    if(a[t]+y==t-h+1)

                        printf("%d\n",max(a[t],y));    

                    else

                    {

                        s=a[t];

                        p=rmq(h+y,t-s);

                        r=max(p,y);

                        printf("%d\n",max(r,s));

                    }

                }

            }

            else

                printf("%d\n",t-h+1);

        }

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: