Shuffle(預處理+暴力)
阿新 • • 發佈:2018-12-30
題目大意:有一個播放器用於播放音樂,現在給出s(已有曲目的數量),n給出記錄的長度。播放器有隨機播放的功能,每次生成一個1~s的隨機系列進行播放,當s首歌全部播放完後,重新生成一個播放序列。現在有一段長度為n的播放記錄片段(即不完全,前後可能還有歌曲),問說該片段的第一首歌可能處於某個播放序列的哪個位置,輸出位置的可能數。
解題思路:首先維護一個長度為n的區間,遍歷一遍播放序列,判斷每個位置往後s個是否有相同的歌曲,如果有則說明不能作為某個播放序列的開頭。然後列舉記錄片段第一首歌可能存在的位置進行判斷,檢查後面每s個位置是否能作為開頭即可。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 1e5+5; int s, n, p[N], c[N]; bool flag[N]; void init () { scanf("%d%d", &s, &n); int tmp = 0; memset(flag, 0, sizeof(flag)); memset(c, 0, sizeof(c)); for (int i = 0; i < n; i++) { scanf("%d", &p[i]); if (i < s) { if (c[p[i]]) tmp++; c[p[i]]++; } } for (int i = 0; i < n; i++) { if (tmp == 0) flag[i] = true; if (c[p[i]] == 2) tmp--; c[p[i]]--; int k = i + s; if (k >= n) continue; if (c[p[k]]) tmp++; c[p[k]]++; } } bool judge (int x) { for (int i = x; i < n; i += s) if (!flag[i]) return false; return true; } int solve () { memset(c, 0, sizeof(c)); int ans = 0; for (int i = 0; i < s; i++) { if (judge(i)) ans++; if (i >= n) continue; if (c[p[i]]) break; c[p[i]]++; } return ans; } int main () { int cas; scanf("%d", &cas); while (cas--) { init(); printf("%d\n", solve()); } return 0; }