UVa 12174 Shuffle (滑动窗口)

Posted dwtfukgv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa 12174 Shuffle (滑动窗口)相关的知识,希望对你有一定的参考价值。

题意:你正在使用的音乐播放器有一个所谓的乱序播放功能,即随机打乱歌曲的播放顺序。假设一共有s首歌,

则一开始会给这s首歌随机排序,全部播放完毕后再重新随机排序、继续播放,依次类推。注意,当s首歌播放完毕之前不会重新排序。

这样,播放记录里的每s首歌都是1~s的一个排列。给出一个长度为n的1≤s,n≤100000)的播放记录(不一定是从最开始记录的)xi(1≤xi≤s),

你的任务是统计下次随机排序所发生的时间有多少种有多少种可能性。

例如,s=4,播放记录是3,4,4,1,3,2,1,2,3,4,不难发现只有一种可能性:前两首是一个段的最后两首歌,后面是两个完整的段,

因此答案是1;当s=3时,播放记录1,2,1有两种可能:第一首是一个段,后两首是另一段;前两首是一段,最后一首是另一段。答案为2。

析:运用滑动窗口,不过先处理一下。

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
const int  maxn = 350000;
int cnt[maxn], a[maxn], ans[maxn];

int main(){
    int T, s, n;  cin >> T;
    while(T--){
        scanf("%d %d", &s, &n);
        memset(ans, 0, sizeof(ans));
        memset(cnt, 0, sizeof(cnt));
        for(int i = 0; i < s; ++i){
            a[i] = 100010 + i;
            ++cnt[a[i]];
            a[i+s+n] = 200010 + i;
        }

        for(int i = 0; i < n; ++i)
            scanf("%d", &a[i+s]);

        int ok = 0;
        for(int i = 1; i < s + n; ++i){
            int j = s + i - 1;
            if(--cnt[a[i-1]] == 1)  --ok;
            if(++cnt[a[j]] == 2)  ++ok;
            if(ok)   ans[i % s] = 1;
        }

        int res = 0;
        for(int i = 0; i < s; ++i)
            if(!ans[i])  ++res;
        printf("%d\n", res);
    }
    return 0;
}

 

以上是关于UVa 12174 Shuffle (滑动窗口)的主要内容,如果未能解决你的问题,请参考以下文章

UVA - 12174 Shuffle (预处理+滑动窗口)

uva12174 滑动窗口+预处理

Shuffle UVA - 12174 尺取法

Uva12174

UVa11572 Unique Snowflakes (滑动窗口)

Uva11572-Unique Snowflakes(滑动窗口)