P1638 逛画展

链接:这里

AC CODE

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
#define LL long long

using namespace std;

int n, m, mina = INF, minb = 2 * INF;
int a[1000006], mark[2005];

int main(){
	cin >> n >> m;
	for(int i = 1; i <= n; ++i){
		scanf("%d", &a[i]);
	}
	mark[a[1]] = 1;
	int cnt = 1;
	for(int l = 1, r = 1; l <= n; ++l){
		mark[a[l - 1]]--;
		if(mark[a[l - 1]] == 0) cnt--;
		while(cnt < m && r <= n){
			r++;
			if(mark[a[r]] == 0){
				cnt++;
			}
			mark[a[r]]++;
		}
		if(cnt == m && r - l + 1 < minb - mina + 1){
			mina = l, minb = r;
		}
	}
	
	cout << mina << ' ' << minb;
	
	return 0;
}

解题报告

寻找包含所有画师作品的最短序列长度,序列中同一画师可能重复出现,且选取最优解下左端点最小的序列。利用双指针算法

l指针指向左端点,r指针指向右端点,cnt代表序列中已有的画师数量,a[]用来存放画师编号,mark[]用来记录序列中某画师的作品数目。

l从左往右顺序遍历,然后从序列中把第l - 1位作品扔出去,接着r一直往后遍历,把第r位画师的作品扔进去,如果这个画师之前未出现过,即mark[r] == 0,那么计数器++,当cnt == m时,或者r越界时退出,最后判断如果是画师满员了,则对区间长度进行比较,接着更新值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值