Frequent values
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 13771 | Accepted: 5045 |
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
题目连接:http://poj.org/problem?id=3368
解法:数列是不降序列的,可以事先统计一次每一个数在哪个区间、每一个区间的初始位置与结束位置、把每个区间的数字的数量存成一个数组。
举个例子:
假设输入的数列为:1 1 2 2 2 3 3 3 3 5
那么处理之后统计每一个数在哪个区间就是:1 1 2 2 2 3 3 3 4 //把数组分为了4个区间,相同的数放同一个区间 ---记为数组c
初始位置和结束位置,这个好处理用一个结构体来记录:(1,2),(3,5),(6,9),(10,10)
-----记为结构体数组inv
最后一个数组,把每个数的数量装起来得到:2 3 4 1 ----记为数组b
做好这些操作之后,根据输入就可以求值
假设输入的查询为2,10
那么先查一下c[10]-c[2]的值,用于判断输入数据之间差了几个区间
这里算出来差了3个区间
那么先根据inv数组计算首尾两个区间分别有多少数据在2和10区间内,分别做好统计记为max1和max2
然后在计算出去首尾的剩下区间(都是全部区间都在查找范围内的)的最大长度
*转换思路之后其实是查找b数组2号位到3号位之间的区间最大值*
然后比较找一下b[2]和b[3]发现最大值max3=4
然后在max1和max2以及max3中寻找一个最大值就可以了,max1=1,max2=1
所以最大值为4
刚刚上面是一般情况,现在有两个特殊情况要处理
1、c[e]-c[s]==1
这种情况是代表两个区间是相邻的,所以没必要再到b数组里面去找了,因为这个时候已经没有剩下的区间,所以直接比较max1和max2的最大值即可
2、c[e]-c[s]==0
这种情况代表输入的值都在一个区间里面,所以max1和max2也都不存在,只需要直接e-s+1就可以求出答案
在一般情况下,寻找b数组中的区间最大值,可以用很多方法解决
我用的是线段树,但是寻找区间最大值可以用rmq,树状数组
不过这都不是关键,反正这个b数组是不会更新的,所以用什么数据结构来处理都是次要的,关键是方法
-----------------------------------------
以上为全部思路,下面贴出代码
code:
#include<stdio.h> #define MAX_N 500000 struct node{ int l; int r; int max; }; struct msg{ int value; int start; int end; }; node tree[3*MAX_N]; int a[MAX_N+5]; int b[MAX_N+5]; int c[MAX_N+5]; msg inv[MAX_N+5]; int max(int x,int y){ if(x>y) return x; else return y; } void swap(int &s,int &e){ s=s^e; e=s^e; s=s^e; } void build_tree(int left,int right,int root){ tree[root].l=left; tree[root].r=right; if(left==right){ tree[root].max=b[left]; return; } int mid=(left+right)/2; build_tree(left,mid,root*2); build_tree(mid+1,right,root*2+1); tree[root].max=max(tree[root*2].max,tree[root*2+1].max); } int find_max(int left,int right,int root){ if(left==tree[root].l&&right==tree[root].r) return tree[root].max; int mid=(tree[root].l+tree[root].r)/2; if(right<=mid) return find_max(left,right,root*2); else if(left>mid) return find_max(left,right,root*2+1); else return max(find_max(left,mid,root*2),find_max(mid+1,right,root*2+1)); } int main(){ int n,m,i,len,inv_len,s,e; while(scanf("%d",&n)!=EOF){ if(n==0) break; scanf("%d",&m); for(i=1;i<=n;i++) scanf("%d",&a[i]); len=0,inv_len=0; b[++len]=1; c[1]=1; inv[++inv_len].value=a[1]; inv[inv_len].start=1; for(i=2;i<=n;i++){ if(a[i]==a[i-1]){ b[len]++; c[i]=c[i-1]; } else{ b[++len]=1; inv[inv_len].end=i-1; inv[++inv_len].value=a[i]; inv[inv_len].start=i; c[i]=c[i-1]+1; } } inv[inv_len].end=n; build_tree(1,len,1); for(i=1;i<=m;i++){ scanf("%d%d",&s,&e); if(s>e) swap(s,e); int q1=c[s]; int q2=c[e]; int ans; if(q2-q1==1){ int max1=inv[q1].end-s+1; int max2=e-inv[q2].start+1; ans=max(max1,max2); } else if(q2-q1==0){ ans=e-s+1; } else{ int max1=inv[q1].end-s+1; int max2=e-inv[q2].start+1; int max3=find_max(c[inv[q1].end+1],c[inv[q2].start-1],1); ans=max(max(max1,max2),max3); } printf("%d\n",ans); } } return 0; }