UVa 12174 (滑动窗口) Shuffle
首先预处理一下以每个数为结尾的前s个数是否能构成一个1~s的排列。
可以用cnt数组来记录每个数出现的次数和用一个变量记录一共有多少个不同的数出现。
然后枚举每种可能的情况,也就是枚举第一首歌会出现的位置,注意要考虑到不完整的序列。
代码不长,但是那个ok数组写起来有点蛋疼,因为要考虑到不完整序列的存在,改了好久才改对。
1 #include <cstdio> 2 #include <cstring> 3 #include <cassert> 4 5 const int maxn = 100000 + 10; 6 int a[maxn], s, n, cnt[maxn * 2]; 7 bool ok[maxn * 3]; 8 9 inline bool in(int x) { return x >= 1 && x <= n; } 10 11 int main() 12 { 13 //freopen("in.txt", "r", stdin); 14 15 int T; scanf("%d", &T); 16 while(T--) 17 { 18 scanf("%d%d", &s, &n); 19 memset(a, -1, sizeof(a)); 20 for(int i = 1; i <= n; i++) scanf("%d", &a[i]); 21 memset(cnt, 0, sizeof(cnt)); 22 //memset(ok, false, sizeof(ok)); 23 int tot = s; 24 for(int i = 1; i < n + s; i++) 25 { 26 if(in(i-s)) { cnt[a[i-s]]--; if(!cnt[a[i-s]]) tot--; } 27 else tot--; 28 if(in(i)) { cnt[a[i]]++; if(cnt[a[i]] == 1) tot++; } 29 else tot++; 30 ok[i] = tot == s; 31 } 32 33 int ans = 0; 34 for(int x = 1-s; x <= 0; x++) 35 { 36 bool flag = true; 37 for(int i = x; i < n+s; i += s) 38 { 39 if(i <= 0) continue; 40 if(!ok[i]) { flag = false; break; } 41 } 42 if(flag) 43 ans++; 44 } 45 46 printf("%d\n", ans); 47 } 48 49 return 0; 50 }