紫书 习题 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;
}