UVa OJ 12174 - Shuffle

Problem

You are listening to your music collection using the shuffle function to keep the music surprising. You assume that the shuffle algorithm of your music player makes a random permutation of the songs in the playlist and plays the songs in that order until all songs have been played. Then it reshuffles and starts playing the list again.
  You have a history of the songs that have been played. However, your record of the history of played songs is not complete, as you started recording songs at a certain point in time and a number of songs might already have been played. From this history, you want to know at how many different points in the future the next reshuffle might occur.
  A potential future reshuffle position is valid if it divides the recorded history into intervals of length s (the number of songs in the playlist) with the rst and last interval possibly containing less than s songs and no interval contains a specic song more than once.

Input

On the rst line one positive number: the number of testcases, at most 100. After that per testcase:
• One line with two integers s and n (1 ≤ s, n ≤ 100000): the number of different songs in the playlist and the number of songs in the recorded playlist history.
• One line with n space separated integers, x1, x2, … , xn (1 ≤ xi ≤ s): the recorded playlist history.

Output

One line with the number of future positions the next reshuffle can be at. If the history could not be generated by the above mentioned algorithm, output 0.

Sample Input

4
4 10
3 4 4 1 3 2 1 2 3 4
6 6
6 5 4 3 2 1
3 5
3 3 1 1 1
7 3
5 7 3

Sample Output

1
6
0
7

Solution

一開始沒想太多,直接用枚舉的方式,寫了一下代碼,提交之後雖然AC了,但是耗時2s多,內心還是不舒服的。於是嘗試改了一下,也參考了別人的代碼。

總體說來還是一道滑動窗口的題目,並不是十分複雜,但是處理得當的話,效率能提升很多。這裏爲了節省時間,通過一次掃描,將每一段可以構成音樂單的數字,用idx這個數組來保存,可以爲1,不行則爲0.最後再將第一個數字按順序,先當成第一段的最後一個,再當成第一段的倒數第二個,以此類推,得到結果。

#include <iostream>
#include <cstring>
using namespace std;

const int maxn = 100005;
int ans, cas, s, n;
int x[3*maxn], idx[maxn<<1], cnt[maxn];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> cas;
    while (cas--){
        cin >> s >> n;
        memset(x, 0, sizeof(int)*(n+(s<<1)+1));
        memset(cnt, 0, sizeof(int)*(s+1));
        memset(idx, 0, sizeof(int)*(n+s+1));
        for (int i = 0; i < n; ++i) cin >> x[i+s];

        int tot = 0;
        for (int i = 0; i < n + s + 1; ++i){
            if ((tot == s) || (i < s && tot == i) || (i > n && tot == n + s - i)) 
                idx[i] = 1;

            if (x[i] && !--cnt[x[i]]) --tot;
            if (x[i + s] && !cnt[x[i + s]]++) ++tot;
        }

        ans = 0;
        for (int i = 0; i < s; ++i) {
            bool isOK = true;
            for (int j = i; j < n + s + 1; j += s) {
                if (!idx[j]){
                    isOK = false;
                    break;
                }
            }
            if (isOK) ++ans;
        }
        if (ans > n) ans = s;
        cout << ans << '\n';
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章