Time Limit: 2000MS | Memory Limit: 65536K | |
Total 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 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个数,非降序排列,有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-6 using 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; }