Frequent values(POJ-1806)(RMQ)

Problem 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

大意: 給定一個不遞減長度爲n的序列,給定m個詢問,每次詢問[li,ri]內上鏡率最高的那個數的出現次數。

由於題中說明輸入數據是一個非遞減數列,可以知道相等的數字都集中在一起,然後可以將它們按出現的次數存入另一個數組運用RMQ求出區間出現的最大值,這時候要處理好左邊界,由於數字如果相等則數組是從左往右遞增的我們要處理好左邊界。

例子:

輸入的數組 :1 2 3 4 4 4 4 4 4 3 3 3 

轉化後數組: 1 1 1 1 2 3 4 5 6 1 2 3

這個時候查詢9-11這個區間  轉化後的數組爲 6 1 2,如果直接找最大值就是6,而正確答案是2.

所以要先從左邊界開始找到一個不大於1的值並用sum記錄下來,之後再用RMQ求最值與sum比較求得答案。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
typedef long long LL;
const int N=100099;
int dp[N][30],a[N],num[N];
void RMQ(int n)
{
    for(int i=1; i<=n; i++)
    {
        dp[i][0]=a[i];
    }

    for(int j=1; (1<<j)<=n; j++)
    {
        for(int i=1; (i+(1<<j)-1)<=n; i++)
        {
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }

    }
}
int main()
{
    int n,q;
    while(scanf("%d",&n)&&n)
    {
        memset(dp,0,sizeof(dp));
        memset(a,0,sizeof(a));
        scanf("%d",&q);
        for(int i=1; i<=n; i++)
            scanf("%d",&num[i]);
        //記錄出現次數
        for(int i=1; i<=n; i++)
        {
            if(i==1)
            {
                a[i]=1;
                continue;
            }
            if(num[i]==num[i-1])
                a[i]=a[i-1]+1;
            else
                a[i]=1;
        }
        RMQ(n);
        while(q--)
        {
            int x,y,sum=0;
            scanf("%d%d",&x,&y);
            while(a[x]>1&&x<=y) //處理左側邊界 記錄sum的值
            {
                if(a[x]>1)
                {
                    sum++;
                    x++;
                }
                else break;
            }
            if(x>=y&&sum==0) printf("1\n");//如果數組中出現 1 1這樣的值
            else if(x>=y&&sum!=0) printf("%d\n",sum);//如果出現數組中7 1這樣的值
            else
            {
                int k=log10(y-x+1)/log10(2);
                int mi=max(dp[x][k],dp[y-(1<<k)+1][k]);
                mi=max(mi,sum);
                printf("%d\n",mi);
            }
        }
    }

    return 0;



發佈了33 篇原創文章 · 獲贊 12 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章