标签:数据 while main 记录 单位 必须 cst 代码 序列
博览馆正在展出由世上最佳的 \(M\) 位画家所画的\(N\)幅图画。可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字,\(a\)和\(b\),代表他要看展览中的第 \(a\) 幅至第 \(b\) 幅画(包含 \(a\) 和 \(b\))之间的所有图画,而门票的价钱就是一张图画一元。
为了看到更多名师的画,你希望入场后可以看到所有名师的图画(至少各一张)。可是你又想节省金钱。。。
请你写一个程序决定购买门票时的 \(a\) 值和 \(b\) 值。数据保证有解,如果存在多个解,则输出 \(a\) 最小的那个解。
\(1 \leq N \leq 1000000\)
\(1 \leq M \leq 2000\)
很明显的双指针,就是右指针每往前推进一个单位,左指针指向的元素如果在这段序列中出现了不止\(1\)次,那么左指针可以往前推进。
序列中每个画家有几幅作品可以通过维护一个数组实现。
判断是否满足条件,可以记录一个\(sum\),新出现一个画家,那么\(sum + 1\)。当\(sum = m\)时,说明满足条件了。
序列中作品的数量可以用左右指针的距离来判断。
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1000010, M = 2010;
int n, m;
int a[N], q[N];
int cnt[M];
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
int hh = 0, tt = -1;
int l = 1, r = n;
int sum = 0;
for(int i = 1; i <= n; i ++) {
if(!cnt[a[i]]) sum ++;
cnt[a[i]] ++;
while(tt >= hh && cnt[a[q[hh]]] >= 2) {
cnt[a[q[hh]]] --;
hh ++;
}
q[++ tt] = i;
if(sum == m && q[tt] - q[hh] < r - l) {
l = q[hh], r = q[tt];
}
}
printf("%d %d\n", l, r);
return 0;
}
标签:数据 while main 记录 单位 必须 cst 代码 序列
原文地址:https://www.cnblogs.com/miraclepbc/p/14459485.html