【图灵杯 E也即POJ 3368】简单的RMQ

Description
给定一个数组,其中的元素满足非递减顺序。任意给定一个区间[i,j],求其中某个元素重复出现的最大次数。

Input
多组数据输入。每组数据的第一行包含两个整数n和q(1<=n,q<=100000),下一行包含n个整数a1,…,an(-100000<=ai<=100000,i∈{1,…,n}),用空格分隔,数列是升序的(ai<=ai+1)。接下来的q行,每行包含两个整数i和j(1<=i<=j<=n),表示给定区间[i,j]。
输入结束于0(自成一行)。

Output
对输入的q个区间,每个区间输出一个整数表示该区间内重复最多的元素出现的次数,用换行分隔。

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

【题目链接】:http://oj.acmclub.cn/problem.php?cid=1162&pid=4

【题意】

【题解】

构造一个数组b;

if(a[i]==a[i-1])
    b[i] = b[i-1]+1;
else
    b[i] = 1;


这个b数组
就表示第i个数字前面有多少个连续数字是和它相等的;
这样对于每一个区间L,R
除了最左端的b[L]以及右端的连续的a[i]==a[L]的位置不能肯定就一定有B[L]个以外,其他的都能确定出现次数最多的就是b的最大值;
这里可以再O(N)求出从该位置开始往后连续的有多少长度和这个位置的a[i]相同;设为dp[i]
则一开始令t=min(dp[L],R-L+1),L=L+dp[i];
然后取【L,R】中的b的最大值和t取较大值作为答案;(L>R的话,答案就是t)

【Number Of WA

1

【完整代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N = 1e5;
int n, q;
int a[N+5], b[N+5], mx[N<<2],dp[N+5];
void build(int l,int r,int rt)
{
    if(l==r)
    {
        mx[rt] = b[l];
        return ;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
    mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l && r<=R)
        return mx[rt];
    int m = (l+r)>>1;
    int ans = 1;
    if(L<=m)
        ans = max(ans,query(L,R,lson));
    if(R>m)
        ans = max(ans,query(L,R,rson));
    return ans;
}
int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    //ios::sync_with_stdio(false);
    while(scanf("%d",&n)!=EOF)
    {
        if (n==0) break;
        scanf("%d",&q);
        a[0] = -1e7;
        memset(b,0,sizeof(b));
        for(int i=1; i<=n; ++i)
        {
            scanf("%d",&a[i]);
            if(a[i]==a[i-1])
                b[i] = b[i-1]+1;
            else
                b[i] = 1;
        }
        dp[n] = 1;
        for (int i = n-1;i >= 1;i--)
            if (a[i+1]==a[i]){
                dp[i] = dp[i+1]+1;
            }
            else
                dp[i] = 1;
        build(1,n,1);
        while(q--)
        {
            int L,R;
            scanf("%d%d",&L,&R);
            int t=0;
            t = min(dp[L],R-L+1);
            L = L + t;
            if(L>R)
                printf("%d\n",t);
            else
                printf("%d\n",max(t,query(L,R,1,n,1)));
        }
    }
}
posted @ 2017-10-04 18:44  AWCXV  阅读(142)  评论(0编辑  收藏  举报