1. 程式人生 > >Shuffle(預處理+暴力)

Shuffle(預處理+暴力)

題目大意:有一個播放器用於播放音樂,現在給出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;
}