12174

  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
Per testcase:
• 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

题意理解:

  给定长度为n的播放历史记录,推断下一次重排的时间点的可能情况数目。注意首尾两段的记录允许不完整(小于s)。

  特殊情况:当n<s时,如果记录中的每首歌均无重复,比如:

  7 3

  5 7 3

  5号歌之前可能还存在1~7(大于7时的情况是等效的)首歌已经播放却没有加入记录,那么下一次重排点就有这7种情况。

解题思路:

  使用滑动窗口的思想进行预处理:对n中的第i个数,如果紧随其后的s个数均没有重复,那么以i为起始的窗口是合法的。 

  

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <ctime>
 5 #include <set>
 6 #define time_ printf("time = %f
",double(clock())/CLOCKS_PER_SEC)
 7 using namespace std;
 8 const int maxn=100000;
 9 int s,n;
10 int seq[maxn+5];
11 int num[maxn+5];
12 int id[maxn+5];
13 
14 void pre_process(){
15     int l=0,r=0;
16     memset(num,0,sizeof num);
17     memset(id,0,sizeof id);
18     int single=0;
19     for(;r<l+s&&r<n;r++){
20         int id=seq[r];
21         num[id]++;
22         if(num[id]==1) single++;
23         else single--;
24     }
25     if(single==r-l) id[l]=1;
26     while(l<n){
27         int a=seq[l];
28         int b=seq[r];
29         num[a]--;
30         if(num[a]==0) single--;
31         if(num[a]==1) single++;
32         l++;
33         if(r!=n){
34             num[b]++;
35             if(num[b]==1) single++;
36             if(num[b]==2) single--;
37             r++;
38         }
39         if(l!=n&&single==r-l) id[l]=1;
40     }
41 }
42 int main(int argc, const char * argv[]) {
43     int T;
44     scanf("%d",&T);
45     while(T--){
46         scanf("%d%d",&s,&n);
47         for(int i=0;i<n;i++)
48             scanf("%d",&seq[i]);
49         pre_process();
50         int ans=0;
51         int rst[maxn+5];
52         memset(rst,0,sizeof rst);
53         rst[seq[0]]++;
54         int single=1;
55         for(int d=1;d<=s&&d<=n;d++){
56             bool ok=true;
57             if(single!=d) break;;
58             for(int pt=d;pt<n;pt+=s){
59                 if(id[pt]==0){
60                     ok=false;
61                     break;
62                 }
63             }
64             if(ok) ans++;
65             rst[seq[d]]++;
66             if(rst[seq[d]]==1) single++;
67         }
68         if(n<s&&ans==n)
69             ans=s;
70         printf("%d
",ans);
71     }
72     return 0;
73 }
原文地址:https://www.cnblogs.com/Kiraa/p/5488108.html