紫书 习题 8-17 UVa 11536 (滑动窗口)

这道题说连续子序列, 马上就想到滑动窗口。

注意窗口里面的元素中小于等于k的才是有效元素。记录窗口里面有效元素的个数, 满足了之后开始

缩短窗口, 如果左端点不是有效元素或者即使窗口中存在这个元素的个数大于1, 即使删去还是满足

窗口内有1到k这些元素的时候, 左端点就删去。就这样扫一遍答案就出来了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;

const int MAXN = 1123456;
int a[MAXN], vis[MAXN], n, m, k;

int main()
{
	int T, kase = 0;
	scanf("%d", &T);
	
	while(T--)
	{
		memset(vis, 0, sizeof(vis));
		scanf("%d%d%d", &n, &m, &k);
		a[0] = 1; a[1] = 2; a[2] = 3;
		REP(i, 3, n) a[i] = (a[i-1] + a[i-2] + a[i-3]) % m + 1;
		
		int num = 0, ans = 2e9, l = 0;
		REP(r, 0, n)
		{
			int cur = a[r];
			vis[cur]++;
			if(cur <= k && vis[cur] == 1) num++;
			if(num >= k)
			{
				while(a[l] > k || vis[a[l]] > 1) vis[a[l]]--, l++;
				ans = min(ans, r - l + 1);
			}
		}
		
		if(ans == 2e9) printf("Case %d: sequence nai\n", ++kase);
		else printf("Case %d: %d\n", ++kase, ans);
	}
	
	return 0;	
} 

posted @ 2018-05-12 10:05  Sugewud  阅读(169)  评论(0编辑  收藏  举报