Codeforces 616D Longest k-Good Segment (尺取)

Description

给出一段长度为\(n\)的序列,求包含不同数字数量不超过\(k\)的最长的连续区间。

Input

第一行给出\(n\)\(k\),第二行给出\(n\)个整数表示这个序列。\(1 \leqslant k \leqslant n \leqslant 5 \times 10^5\)

Output

输出两个整数\(l\)\(r\),表示最长区间的左右端点。

Sample Input

5 5
1 2 3 4 5

Sample Output

1 5

Solution

求连续区间,尺取问题。给出上限约束条件。依次推进左端点,对于每个左端点,右端点向右延伸直到找到第一个不合法位置,此时区间长度减一就是此左端点对应的满足条件的最长区间长度。随着左端点的推进,最后会出现不会使条件不成立的情况,此时的区间长度就是此左端点对应的答案。因为之后的区间只会更短,依次更新答案之后跳出即可。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 5e5 + 10;
const int M = 1e6 + 10;

int a[N], cnt[M];

int main()
{
	int n, k;
	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; i++) scanf("%d", a + i);
	memset(cnt, 0, sizeof(cnt));
	int ans = 0, ansl, ansr;
	for (int l = 1, r = 1, num = 0; l <= n; l++)
	{
		while (r <= n && num <= k)
		{
			cnt[a[r]]++;
			if (cnt[a[r]] == 1) num++;
			r++;
		}
		if (num <= k)
		{
			if (r - l > ans)
			{
				ans = r - l;
				ansl = l;
				ansr = r - 1;
			}
			break;
		}
		if (r - 1 - l > ans)
		{
			ans = r - 1 - l;
			ansl = l;
			ansr = r - 2;
		}
		cnt[a[l]]--;
		if (cnt[a[l]] == 0) num--;
	}
	printf("%d %d\n", ansl, ansr);
	return 0;
}

http://codeforces.com/problemset/problem/616/D

posted @ 2017-08-13 15:29  达达Mr_X  阅读(288)  评论(0)    收藏  举报