您的位置:首页 > 产品设计 > UI/UE

poj 3368 Frequent values(离散化+RMQ)

2013-09-27 21:56 441 查看
Frequent values
Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 11820Accepted: 4320
DescriptionYou 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.InputThe 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 thequery.The last test case is followed by a line containing a single 0.OutputFor 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-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=i;}A++;}initRMQ();while(m--){scanf("%d%d",&a,&b);printf("%d\n",RMQ(a,b));}}return 0;}
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: