题意:给一个数组,记数组中出现次数最多的元素出现的次数为这个数组的美丽值,求这个数组长度最短的子数组(要连续),使得该子数组的美丽值与原数组美丽值相等。要求输出子数组的起始和结束位置下标(从1开始)。
也是个水题。每个数最大才10^6,用hash存储每个数出现的次数即可。注意有可能有多个不同的元素出现的次数都相等且为最大,需要一一判断。遍历数组的时候可以用两个值 l[i],r[i] 维护每个数最左出现的位置和最右出现的位置。这样可以直接计算长度。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
const int MAX = 1000005;
const int INF = 100005;
int n, a[INF], cnt[MAX], start[MAX], finish[MAX], number; //start起始下标,finish结束下标,number美丽值
void input()
{
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < MAX; i++)
{
start[i] = INF;
finish[i] = 0;
}
number = 0;
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
cnt[a[i]]++;
start[a[i]] = min(start[a[i]], i + 1); //维护起始下标
finish[a[i]] = max(finish[a[i]], i + 1); //维护结束下标
number = max(number, cnt[a[i]]);
}
}
void solve()
{
int l = 0, r = n;
for(int i = 0; i < n; i++)
{
if(cnt[a[i]] == number)
{
if(finish[a[i]] - start[a[i]] < r - l) //长度更短
{
l = start[a[i]];
r = finish[a[i]];
}
}
}
printf("%d %d\n", l, r);
}
int main()
{
while(scanf("%d", &n) != EOF)
{
input();
solve();
}
return 0;
}