UVA12173Shuffle:尺取法

题意

  • 总共有s首歌,播完s首歌,打乱顺序,再继续播这s首。
  • 给你n首歌的播放记录,请问下一首歌的情况有多少种。

题解

  • 如果[i-s,i]能够成为一轮歌单,那么一定没有重复的歌。如果第i首歌和之前的重复了,那么[i-s,i]不会成为完整的歌单,同理[i+(k-1)*s,i+k*s]也不可能是一轮歌单。所以我们给i%s做上标记,它代表以i+k*s结尾的歌单

代码

#include <bits/stdc++.h>
using namespace std;
int const N = 100000 + 10;
int s,n,a[N],ans[N],num[N],tot;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		memset(ans,true,sizeof(ans));
		memset(num,0,sizeof(num));
		tot = 0;
		scanf("%d%d",&s,&n);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		int tmp;
		for(int i=1;i<=n+s;i++){
			if(i <= n && ++num[a[i]]==1) ++tot;
			if(i > s && --num[a[i-s]]==0)	--tot;
			if(i % s == 0)	tmp = s;
			else	tmp = i % s;
			if(min(i,n) - max(i-s,0) != tot)	ans[tmp] = false;    //这一句好好领悟
		}
		int res = 0;
		for(int i=1;i<=s;i++)
			if(ans[i])	res++;
		printf("%d\n",res);
 	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/88827581