测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A22071. 宝石项链

填空题 困难

题目描述

宝石项链

题目描述

小 A 有一串包含 n 枚宝石的宝石项链,这些宝石按照在项链中的顺序依次以 1,2,…,n 编号,第 n 枚宝石与第 1 枚宝石相邻。项链由 m 种宝石组成,其中第 i 枚宝石种类为 ti

小 A 想将宝石项链分给他的好朋友们。具体而言,小 A 会将项链划分为若干连续段,并且需要保证每段都包含全部 m 种宝石。请帮小 A 计算在满足条件的前提下,宝石项链最多可以划分为多少段。

输入格式

第一行,两个正整数 n, m,分别表示宝石项链中的宝石的数量和种类数。

第二行,n 个正整数 t1,t2,…,tn,表示每枚宝石的种类。

输出格式

输出一行,一个整数,表示宝石项链最多可以划分为多少段。

样例

输入样例 1

6 2
1 2 1 2 1 2

输出样例 1

3

输入样例 2

7 3
3 1 3 1 2 1 2

输出样例 2

2

数据范围

对于40的测试点,保证2≤n≤1000。

对于所有测试点,保证2≤n≤105,2≤m≤n,1≤ti≤m,保证1,2....,m均在 t1,t2,…,tn中出现。

参考答案

#include<cstdio> #include<algorithm> using namespace std; const int L = 20; const int N = 2e5 + 5; const int oo = 1e9; int n, m; int t[N], m[N]; // 注意原始代码里有int t[N], m[N]; 这里m和前面的m变量重名,保留原始 int cnt[N], jump[L][N]; int ans, tot; int go(int u) { int cnt = 0, ans = 0; for (int i = L - 1; i >= 0; i--) if (cnt + jump[i][u] <= n) { cnt += jump[i][u]; ans += 1 << i; u = (u + jump[i][u] - 1) % n + 1; } return ans; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &t[i]); t[i + n] = t[i]; } for (int i = 1, r = 0; i <= n; i++) { while (tot < m) { r++; if (!cnt[t[r]]++) tot++; } jump[0][i] = r - i + 1; if (!--cnt[t[i]]) tot--; } for (int i = 1; i < L; i++) { for (int j = 1; j <= n; j++) { int tar = (j + jump[i - 1][j] - 1) % n + 1; jump[i][j] = min(jump[i - 1][j] + jump[i - 1][tar], oo); } } for (int i = 1; i <= n; i++) ans = max(ans, go(i)); printf("%d\n", ans); return 0; }
上一题 下一题