是参考了别人的代码学习的一种解法,总体思路是贪心算法,用一个不断更新的动态区间去找到最优解,当遍历完所有的画,最终确立的区间就是最优区间
这个区间的要求是要至少有每一位大师的一幅画,根据这个原则确定区间的边界,因此再开一个数组,记录当前区间包含的每位大师的画数,每位大师的画数>=1,判断不需要遍历当前这个数组来判断是否满足要求。
而是看更新完端点后,当前端点的画对应的大师编号,看这个大师的画数是否>=1,因为这个区间满足至少有每一位大师的一幅画这个条件,而改变区间端点只有当前端点的画对应的大师编号的画数变化,这样优化了判断条件
代码如下:
#include<stdio.h>
int b[2001];
int a[1000010];
//定义全局变量这样数组元素初始值为0
int main()
{
int num = 0;
int r = 0, l = 1, n, m, ansl, ansr;
scanf("%d%d", &n, &m);
for (int j = 1; j <= n; j++)
scanf("%d", &a[j]);
int i = 1;
while (num != m)
{
if (b[a[i]] == 0)num++;
//左端点初始值为0,不断更新右端点,直到覆盖所有画师的画,也就是num==m
b[a[i]]++;
r++;
i++;
}
//开始缩小区间,只要对应画师的画数大于1就可以保证看完所有的画
while (b[a[l]] > 1)
b[a[l++]]--;
ansl = l; ansr = r;
//当且仅当这个区间才可以满足看完所有画师的话,循环结束
//上面的步骤相当于给这个最小的区间赋一个初值,下面开始不断优化区间
while (i < n)
{
//遍历右边的画让画师对应的画数增加,因此又可以移动左边的区间端点
b[a[i]]++;
r++;
i++;
while (b[a[l]] > 1)
b[a[l++]]--;
//如果现在的区间更好,那么就更新答案区间,直到遍历完全部画,得到最优区间
if (ansr - ansl > r - l)
{
ansr = r;
ansl = l;
}
}
printf("%d %d", ansl, ansr);
}