poj 3368 Frequent values(离散化+RMQ)

来源:互联网 发布:java堆内存溢出 编辑:程序博客网 时间:2024/06/16 17:20
Frequent values
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 11820 Accepted: 4320

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 indicesi and j (1 ≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integersai , ... , aj.

Input

The input consists of several test cases. Each test case starts with a line containing two integersn and q (1 ≤ n, q ≤ 100000). The next line containsn integers a1 , ... , an (-100000 ≤ ai ≤ 100000, for eachi ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: ai ≤ ai+1. The followingq 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 102 31 105 100

Sample Output

143
题意:给出n个数,非降序排列,有q个询问,对于每个询问a,b,求出区间[a,b]中的出现次数最多的数的出现次数。
思路:先将数据离散化,用x[i]表示原数组,A[i]表示离散化后下标为i的数在原序列的出现次数,s[i]表示离散化后下标为i的数在原数组中第一次出现的位置,in[i]表示i离散化后的下标,然后rmq[i][k]存的是从i开始长度为1<<k的区间的最大A[i]值。对于每个询问(a,b),有三种情况:
(1)若x[a]==x[b],那么这个区间只有一个元素,答案为b-a+1。
(2)若in[x[a]]+1==in[x[b]],即这个区间只有两种元素,答案为两种元素在这个区间出现次数的最大值
(3)若区间的元素种数>2,则先求出首尾两种元素出现次数的最大值,因为中间的元素一定全部落在区间[a,b]上,所以可用RMQ求出中间元素出现次数的最大值。
AC代码:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <cmath>#include <cstdlib>#define L(rt) (rt<<1)#define R(rt) (rt<<1|1)#define ll long long#define eps 1e-6using namespace std;const int maxn=100005;int A[maxn+20],s[maxn+20],x[maxn+20],in[maxn*2+20],rmq[maxn+20][30];//x[i]表示原数组//A[i]表示离散化后下标为i的数的出现次数//s[i]表示离散化后下标为i的数在原数组中第一次出现的位置//in[i]表示i离散化后的下标//rmq存最大的出现次数int n,m,num;void initRMQ(){    for(int i=1;i<=n;i++) rmq[i][0]=A[i];    for(int k=1;(1<<k)<=n;k++)    for(int i=1;i+(1<<k)-1<=n;i++)    rmq[i][k]=max(rmq[i][k-1],rmq[i+(1<<(k-1))][k-1]);}int RMQ(int a,int b){    int ia=in[x[a]],ib=in[x[b]];  //ia,ib分别是x[a],x[b]离散化后的下标    if(ia==ib) return b-a+1;      //即x[a]==x[b]    int sb=s[ib]; //sb分别为x[b]在x数组第一次出现的下标    if(ia+1==ib) return max(sb-1-a+1,b-sb+1); //若[a,b]内只有两种元素    int ans=max(s[ia+1]-1-a+1,b-sb+1);  //ans为首尾的最大值    ia++;    ib--;    int k=(int)(log(ib-ia+1.0)/log(2.0));    ans=max(ans,max(rmq[ia][k],rmq[ib-(1<<k)+1][k]));    return ans;}int main(){    int a,b;    while(scanf("%d",&num),num)    {        scanf("%d",&m);        n=0;x[0]=0;        memset(A,0,sizeof(A));        for(int i=1;i<=num;i++)        {            scanf("%d",&x[i]);            x[i]+=maxn;            if(x[i]!=x[i-1])            {                in[x[i]]=++n;                s[n]=i;            }            A[n]++;        }        initRMQ();        while(m--)        {            scanf("%d%d",&a,&b);            printf("%d\n",RMQ(a,b));        }    }    return 0;}