Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 17832 | Accepted: 6427 |
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
这个题我是被自己感动到了,没想到自己做的第二个RMQ的题可以一次就过,编译也是一次过,太感动了!
哈哈!
题意是:给出一个非降序的整数数组,你的任务是对于一系列询问,回答区间内出现最多的值的次数
说一下如何做
正如《算法竞赛入门经典(训练指南)》198页讲的,
这里我们因为是按非降序排列的,那也就是说相同的数字一定是在一起的
这里我们就用相同的数字为一段来描述
那么说例题中我们就有2 4 1 3分别代表四段
我们用a[]数组来存给出的值,
下面说说我们用到的数组的意义
value[]: 代表第i段的具体数值
coun[]: 代表第i段出现的次数
lef[] : 代表第i段的左端点的位置
righ[]: : 代表第i段的右端点的位置
num[] 数组稍有不同 他指的是第p个位置上为第几段
这样我们只要找num[L]+1, num[R]-1段中的最大值与righ[L]-L+1, R-lef[R]+1,三个中的最大值就可以了,
当然特殊情况也要有考虑
大致可分为三种:
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int inf = INT_MAX;
int value[300005], coun[300005];
int num[300005], lef[300005], righ[300005];
int a[300005], b[300005][20];
int top;
void inti()
{
a[0] = inf;
top = 0;
}
void RMQ()
{
int i, j;
for ( i = 1;i <= top; i++ )
b[i][0] = coun[i];
for ( j = 1;(1<<j) <= top; j++ )
{
for ( i = 1;i+(1<<(j-1)) <= top; i++ )
b[i][j] = max(b[i][j-1], b[i+(1<<(j-1))][j-1]);
}
}
int RMQ_check(int y, int x)
{
int nb = 0;
while ( (1<<nb) <= y-x+1 )
nb++;
return max(b[y-(1<<(nb-1))+1][nb-1], b[x][nb-1]);
}
int main()
{
int i, n, m;
int L, R;
while ( ~scanf ( "%d", &n )&&n != 0 )
{
scanf ( "%d", &m );
inti();
for ( i = 1;i <= n; i++ )
{
scanf ( "%d", &a[i] );
if ( a[i] != a[i-1] )
{
righ[top] = i-1;
top++;
lef[top] = i;
value[top] = a[i];
coun[top] = 0;
}
num[i] = top;
coun[top]++;
}
righ[top] = n;
RMQ();
for ( i = 0;i < m; i++ )
{
scanf ( "%d %d", &L, &R );
if ( num[L] == num[R] )
printf ( "%d\n", R-L+1 );
else if ( num[R]-num[L] == 1 )
printf ( "%d\n", max(righ[num[L]]-L+1, R-lef[num[R]]+1) );
else
{
int ma1 = righ[num[L]]-L+1;
int ma2 = R-lef[num[R]]+1;
int ma3 = RMQ_check(num[R]-1, num[L]+1);
printf ( "%d\n", max(ma1, max(ma2, ma3)));
}
}
}
return 0;
}
代码菜鸟,如有错误,请多包涵!!!
如有帮助记得支持我一下,谢谢!!!