## 24737: 【USACO2013JAN】奶牛排队{ Gold题1}

[提交][状态][讨论版][命题人:]

## 题目描述

3. 奶牛排队{ Gold1}

【问题描述】

约翰觉得如果连续排列的一段奶牛有相同的血统编号的话，奶牛们看起来会更具有威猛。为了创造这样的连续段，约翰最多能选出k种血统的奶牛，并把他们全部从队列中赶走。

【文件输入】

【文件输出】

一行，一个整数，表示所能得到的最大连续段的长度

【输入样例】

9 1

2

7

3

7

7

3

7

5

7

【输出样例】

4

【样例说明】

## 提示

原题目其实可以等价为：选择一段区间[i,j]，使得区间内至少有k+1中颜色，定义Ai表示这一段区间最多的一种颜色的个数。那么答案显然就是max{Ai}了。

枚举区间左右端点肯定是不行的，我们只需要枚举左端点，而右端点可以继承上一个右端点的位置，然后往后延展至满足条件的最远处。而取区间内颜色最多的一种，我们只需要用一个堆或者优先队列来动态维护即可。

进一步思考，维护区间内数量最大的牛的数量需要用到堆或者优先队列。事实上，在最有解所对应的区间，最左端的牛必定是数量最多的牛，所有在枚举左端点时，我们就假定当前左端点的牛的数量为最大值，往右边扫描即可，假设当前满足的区间是[L,R]，则考虑L+1为左端点时，右端点直接从R开始考虑。故算法的复杂度可以降到O(N)

Analysis: Cow Lineup by Travis Hance

This problem is equivalent to（等价于） finding, out of all contiguous
subintervals（连续子区间）
containing at most K+1 distinct（不同的） breed IDs, the maximal number of cows of a single breed
contained within such an interval.

The idea is to sweep down the array of cows, keep tracking of the left and
right endpoints of an interval. Each time we increment the right endpoint, we
may need to increment the left endpoint by some amount so that the interval
contains at most K+1 distinct IDs. Of course, when we do this, we will
increment the left endpoint as little as possible. To do this, we just need to
keep track of (i) for each breed ID, how many cows of that ID are in the
interval and (ii) how many distinct breed IDs have a nonzero number of cows in
the interval.

Now, when examining any interval（区间）, we need to know the maximal number of
cows of a single breed in that interval. One approach is to use a data
structure such as a set or priority queue to maintain the maximum. Since at
most K+1 IDs are nonzero at any given time, this solution takes O(N log(K))
time.

An even simpler approach involves the observation that during this sweep
process, at some point the left endpoint will actually be pointing to the
correct breed ID, and at this time the interval will contain as many cows of
that ID as possible. In other words, rather than asking "Given an
interval, what is the maximal number of cows of a single ID within this
interval?", we ask "Given a cow, what is the maximum number of cows
of that ID which can be in an interval with that cow as the left
endpoint?" This solution takes O(N) time.

Here is Mark Gordon's solution in C++:

#include
<iostream>

#include
<cstdio>

#include
<map>

#include
<set>

using
namespace std;

int
A[100010];

int
main() {

freopen("lineup.in", "r",
stdin);

freopen("lineup.out",
"w", stdout);

int N, K; cin >> N >> K;

for(int i = 0; i < N; i++) {

cin >> A[i];

}

int res = 0;

int nz_cnt = 0;

map<int, int> cnt;

for(int i = 0, j = 0; i < N; i++) {

int& ci =
cnt[A[i]];

if(ci == 0)
nz_cnt++;

ci++;

for(; nz_cnt
> K + 1; j++) {

int&
cj = cnt[A[j]];

--cj;

if(cj == 0) nz_cnt--;

}

res = max(res,
ci);

}

cout << res
<< endl;

return
0;

}

[提交][状态]