UVALive - 4294 Shuffle 映射+取反+最大区间覆盖

来源:互联网 发布:志鸿优化系列赢在高考 编辑:程序博客网 时间:2024/06/02 05:31

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 lengths (the number of songs in the playlist) with the first and last interval possibly containing less than s songs and no interval contains a specific song more than once.

Input

On the first line there exists one positive number: the number of test cases, at most 100. After that per test case there exists:

• 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 test case there exists:

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

Sample Input

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


Source

UVALive - 4294


My Solution

题意:歌曲种数为s,记录的数量为n,然后给出这个n个记录,每s个歌会随机播放一遍,然后开始重新随机播放这s首歌,为未来可能在几个点进行一次新的循环。

映射+取反+最大区间覆盖
扫一遍数组,每次如果i - last[v[i]] < s,则点x必须是在这个区间里划分,然后新的循环会在kx之后出现,

所以把i和last[v[i]]映射到 [0, s) 里,
然后如果 (i % s) > (last[v[i]] % s) 则答案在区间[(last[v[i]] % s), (i % s))里,取反以后
是答案不可能在 [0, (last[v[i]] % s) ) 和[(i % s), s)里。
如果 (i % s) < (last[v[i]] % s) 则答案在区间 [0, (i % s)) 和[(last[v[i]] % s), s)里,取反以后
答案不可能在区间[(i % s), (last[v[i]] % s))里
然后跑一遍把所有的不可能区间搞出来,然后就是最大区间覆盖问题,ans = s - 最大区间覆盖
复杂度 略大于O(n) 远小于 O(nlogn)


#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 1e5 + 8;const int INF = 1e9 + 7;int v[maxn], last[maxn];struct interval{    int l, r;    interval(int x, int y) : l(x), r(y) {}};vector<interval> val;inline bool cmp(const interval& a, const interval& b){    if(a.l != b.l) return a.l < b.l;    else return a.r < b.r;}int main(){    #ifdef LOCAL    freopen("h.txt", "r", stdin);    //freopen("h.out", "w", stdout);    #endif // LOCAL    //ios::sync_with_stdio(false); cin.tie(0);    int T, s, n, i, j, sz, ans;    scanf("%d", &T);    while(T--){        val.clear();        memset(last, -1, sizeof last);        scanf("%d%d", &s, &n);        for(i = 0; i < n; i++){            cin >> v[i];            if(last[v[i]] != -1){                if(i - last[v[i]] < s){                    if((i % s) > (last[v[i]] % s)){                        val.push_back(interval(0, (last[v[i]] % s)));                        val.push_back(interval((i % s), s));                    }                    else{                        val.push_back(interval((i % s), (last[v[i]] % s)));                    }                }            }            last[v[i]] = i;        }        sort(val.begin(), val.end(), cmp);        sz = val.size();        ans = s;        for(i = 0; i < sz; i++){            if(i + 1 < sz && val[i].r >= val[i + 1].l) {                val[i + 1].l = val[i].l; val[i].l = INF; val[i+1].r = max(val[i].r, val[i + 1].r);            }            else{                ans -= val[i].r - val[i].l;            }        }        printf("%d\n", ans);    }    return 0;}


  Thank you!

                                                                                                                                               ------from ProLights

1 0
原创粉丝点击