poj 3368(RMQ简单应用)

Frequent values

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 13317   Accepted: 4894

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

详细参考刘汝佳的算法训练指南第198页,看了就懂了。

AC代码:

#include<stdio.h>
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int a[100010];
int val[100010],counter[100010];
int num[100010],Left[100010],Right[100010];
int d[100100][110];
int n,q;
void RMQ_init(){
    int i,j,k;
    int tmp;
    val[1]=a[1];
    k=num[1]=Left[1]=1;
    for(i=2;i<=n;i++){
        if(a[i]!=val[k]){
            Right[k]=i-1;
            counter[k]=Right[k]-Left[k]+1;
            k++;
            Left[k]=i;
            val[k]=a[i];
        }
        num[i]=k;
    }
    Right[k]=n;
    counter[k]=Right[k]-Left[k]+1;

    for(i=1;i<=k;i++)
        d[i][0]=counter[i];
    for(j=1;(1<<j)<=k;j++)
    for(i=1;i+(1<<j)-1<=k;i++){
        d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    }

}
int RMQ(int x,int y){
    int k=0;
    while((1<<(k+1))<=y-x+1) k++;
    return max(d[x][k],d[y-(1<<k)+1][k]);
}
int main(){
    while(scanf("%d",&n)!=EOF){
        if(n==0)
            break;
        scanf("%d",&q);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        RMQ_init();
        while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            if(num[x]==num[y]){
                printf("%d\n",y-x+1);
            }
            else{
                int ans;
                ans=max(Right[num[x]]-x+1,y-Left[num[y]]+1);
                if(num[x]+1<=num[y]-1){
                    ans=max(ans,RMQ(num[x]+1,num[y]-1));
                }
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}

poj 3368(RMQ简单应用)

时间: 2024-10-13 10:23:54

poj 3368(RMQ简单应用)的相关文章

poj 3368 rmq ***

题意:给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之间连续出现次数最多的次数. 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define

poj 3368 Frequent values(RMQ)

1 /************************************************************ 2 题目: Frequent values(poj 3368) 3 链接: http://poj.org/problem?id=3368 4 题意: 给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之 5 间连续出现次数最多的次数 6 算法: RMQ 7 思路: 借助数组f[i].表示第i位前面有f[i]个相同的数.对于 8 每个区间(l,r).暴力求前面几个

【POJ 3368】 Frequent values(RMQ)

[POJ 3368] Frequent values(RMQ) Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15813   Accepted: 5749 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given seve

POJ 3368 Frequent values

Frequent values Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13051 Accepted: 4792 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 consisti

poj 3368 Frequent values 解题报告

题目链接:http://poj.org/problem?id=3368 题目意思:给出一段 n 个数的序列你,对于区间 [l, r] 的询问,找出 出现频率最高的数的次数.考虑到序列中的数是非递减的,也就是相同的数会连续不间断地在一起,于是就才有了代码中这个部分来预判了: if (s > t)        printf("%d\n", ans); 这个人写RMQ 写得不错:http://dongxicheng.org/structure/lca-rmq/ 这题就是套模板的,纪念

poj 3368 Frequent values(线段树解法)

题目链接:http://poj.org/problem?id=3368 题目大意:给你一段不下降的序列,求给定区间里出现次数最多的那个数字的次数. 思路:首先看到这题时,第一感觉线段树,但是仔细一看问题来啦,用线段数我怎么才能计算出某段区间里出现的那个数,因为出现最多的那个数可能不是在他它的左儿子上也不是在它的右儿子上,可能在当他们合并成一个区间时就出现啦,但是这儿我们需要注意的就是,题目给的是一段不下降的序列,那么突破口就出来啦,因为如果出现相同的数字,那么它们一定是连续的.所以我们只需要在普

POJ 3264 RMQ Spare Table算法

今天下午大帝讲的,我以前也不懂,所以也就跟着学学了,把中间的那个状态转移方程学错了好几次,于是就wa了 好几发. #include<iostream> #include<cstdio> #include<algorithm> #define maxn 200010 using namespace std; int a[maxn],m,n,b[maxn],fl[maxn][50],fr[maxn][50]; void solve() { b[1]=0;//其实就是用来计算

POJ 1469 COURSES //简单二分图

COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17211   Accepted: 6769 Description Consider a group of N students and P courses. Each student visits zero, one or more than one courses. Your task is to determine whether it is poss

(简单) POJ 3368 Frequent values,RMQ。

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 t