题意:已知歌单中的歌曲数目s,和部分的播放历史,问下一首可能播放的歌曲种数。
分析:
1、按照歌单数目s,将播放历史划分为几部分。
2、将播放历史的n首歌曲之前加上s首歌曲,之后加上s首歌曲,为防止标号重复,分别将其标号为100001 + i和200001 + i。
3、枚举这个新的序列中的每首歌,以s首为区间,区间开头为i,结尾为s + i - 1,若该区间里的数字不唯一,则不可能以该区间为标准划分,排除i%s这一划分可能。
4、判断区间里歌曲唯一的方法,记录每首歌出现次数,进入区间则加1,离开区间则减1,若区间长为s,里面每首歌都出现过1次,则此时sum一定为0,区间内是一种可行的播放顺序。
5、为排除之前s首和之后s首对歌曲唯一性判断的影响,只要初始化成之前的歌曲出现次数-1后不为1,之后的歌曲出现次数+1后不为2即可。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 300000 + 10;
const int MAXT = 10000 + 10;
using namespace std;
int a[MAXN];
map<int, int> mp;
bool ans[MAXN];
int s, n;
int solve(){
int sum = 0;
for(int i = 1; i < n + s; ++i){
int et = s + i - 1;
if(--mp[a[i - 1]] == 1) --sum;
if(++mp[a[et]] == 2) ++sum;
if(sum != 0) ans[i % s] = false;
}
int cnt = 0;
for(int i = 0; i < s; ++i){
if(ans[i]){
++cnt;
}
}
return cnt;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
mp.clear();
memset(a, 0, sizeof a);
memset(ans, true, sizeof ans);
scanf("%d%d", &s, &n);
for(int i = 0; i < s; ++i){
a[i] = 100001 + i;
++mp[a[i]];
}
for(int i = 0; i < n; ++i){
scanf("%d", &a[i + s]);
}
for(int i = 0; i < s; ++i){
a[s + n + i] = 200001 + i;
}
printf("%d\n", solve());
}
return 0;
}