Frequent values
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1112 Accepted Submission(s): 399
Problem Description
You are given a sequence of n integers a
1 , a
2 , ... , a
n 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 a
i , ... , a
j .
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 a
1 , ... , a
n(-100000 ≤ a
i ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: a
i ≤ a
i+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.
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 3HintA naive algorithm may not run in time!
题意: 题目给出了一组单调递增的序列,然后有m种操作,每次操作给出一个区间,叫你找出这个区间相同的数的个数最大的那个数的个数,如果直接暴力肯定会超时的。
意解: 首先先统计这一行序列出现的数的个数,在用unique去重,在转化为区间维护最大值,最大值指的是数的个数,然后对于每一个区间的询问,只需找出两个端点的数的
个数,再和中间的数的个数比较得出最大值即可,在这一过程注意考虑一些特殊的情况,加上二分查找询问的区间位置就可以得解了。
一下是AC代码(PS:仅供参考)
真心觉得自己YY出来的算法好开心。
/****************************************************** /
/* /*
* *********** *
* * Auther: ZSGG *
* * *
* * Name: *
* * *
* *********** Algorithm: *
* *
*/
/*******************************************************/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
#include <cstdlib>
#include <algorithm>
#define ls u << 1
#define rs u << 1 | 1
#define lson l, mid, u << 1
#define rson mid + 1, r, u << 1 | 1
using namespace std;
const int M = 1e5 + 5;
int a[M << 1],b[M << 1],c[M << 1];
int sum[M << 2];
int A,B;
void build(int l, int r, int u)
{
if(l == r)
{
int ue = c[l - 1];
sum[u] = a[ue];
// cout<<a[ue]<<endl;
}
else
{
int mid = (l + r) >> 1;
build(lson);
build(rson);
sum[u] = max(sum[ls], sum[rs]);
}
}
int query(int L, int R, int l, int r, int u)
{
if(L <= l && R >= r)
{
return sum[u];
}
int mid = (l + r) >> 1;
int res = 0;
if(L <= mid) res = max( query(L,R,lson), res );
if(R > mid) res = max( query(L,R,rson), res );
return res;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,m;
while(~scanf("%d",&n) && n)
{
scanf("%d",&m);
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
for(int i = 0; i < n; i++)
{
scanf("%d",b + i);
int ue = b[i] + 100000;
b[i] += 100000;
a[ue]++;
}
copy(b, b + n, c);
int ans = unique(c, c + n) - c; //去重
build(1,ans,1);//建树
while(m--)
{
int ua,ub,i,j;
scanf("%d %d",&ua,&ub);
A = B = 1;
ua--;
ub--;
for(i = ua; i <= ub; i++) //左端点第一个相同的数的个数
if((i + 1) <= ub && b[i + 1] == b[i]) A++;
else break;
if(i == ub + 1) //如果这段区间是同一个数,则直接输出;
{
printf("%d\n",A);
continue;
}
for(i = ub; i >= ua; i--)//右端点第一个相同的数的个数
if((i - 1) >= ua && b[i - 1] == b[i]) B++;
else break;
//二分查找区间的端点在新的区间的位置。
ua = lower_bound(c, c + ans, b[ua]) - c + 1;
ub = lower_bound(c, c + ans, b[ub]) - c - 1;
if(ua > ub) //这是一种情况
{
printf("%d\n",max(A,B));
continue;
}
// cout<<ua<<" "<<ub<<endl;
int res = query(ua + 1, ub + 1, 1, ans, 1); //这是简单的区间查找最大值
if(res < A) res = A;
if(res < B) res = B;
printf("%d\n",res);
}
}
return 0;
}
人一我百!人百我万!。。。。。。。。。。。
自由自在!潇洒快乐!。。。。。。。。。。。