您的位置:首页 > 其它

UVA12174_Shuffle

2015-09-10 03:10 387 查看
Shuffle

大致题意:

你有一个随机播放的播放器,有s首歌,在这s首播放完之前不会重新打乱顺序,现在给出一段只含有1~s的n长度序列,现在问你下次随机排序发生的时间有多少种可能

其实就是问你这个播放记录的起点有多少种可能

思路:

先暴力枚举一下开头s个字符分别为起点,然后验证这样是否合法

这样关注的焦点就是如何检验了,暴力显然不行,那么我们就预处理所有可以是一段记录播放起点的点(也就是含这个点后s个字符各不相同),那么检验最开始s个分别是否为合法起点的时候就只要不断枚举他后面第s为起点是否合法就行了,

现在问题又转移到如何知道s个连续序列是否都不相同了,这个就和滑动窗口很像了,

我们只要记录s个字符每个字符的的出现次数和有多少个不同字符串就行了,如果有s个不同字符串就能为起点,每次转移时间区间整体右移一个单位,那么变化的是原来区间的最左端和最右端+1的个数,如果有计数变成1则出现新字符,如果变成0则失去了一个字符



这个程序有一个小技巧,就是在n字符前面添加s个作为形式起点

但这样写出现bug了,原因是我默认n>=s了,而且最后s个字符和最初s个字符不能使用是否有s个不同的字符来检验合法性了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<map>
#include<queue>
#include<vector>

using namespace std;
const int maxn = 3e5+100;
#define pr(x) cout << #x << " = " << x << " ";
#define prln(x) cout << #x << " = " << x <<endl;
#define ll long long
int x[maxn], ok[maxn], cnt[maxn], s, n;
int main(){
#ifdef LOCAL
    freopen("C:\\Users\\User Soft\\Desktop\\in.txt","r",stdin);
  //freopen("C:\\Users\\User Soft\\Desktop\\out.txt","w",stdout);
 #endif
    int t;cin >> t;
    while(t--) {
        cin >> s >> n;
        memset(x, -1, sizeof x);
        memset(cnt, 0, sizeof cnt);
        memset(ok, 0, sizeof ok);
        for(int i = 0; i < n; ++i) {
            scanf("%d", x + s + i);
        }
        int tot = 0;
        for(int i = 0; i < n + s; ++i) {
            if(tot == s) ok[i] = true;
            if(i < s && tot == i) ok[i] = true;
            if(i > n && n + s - i == tot) ok[i] = true;

            if(x[i] != -1 && --cnt[x[i]] == 0) --tot;
            if(x[i + s] != -1 && cnt[x[i + s]]++ == 0) ++tot;
        }
        int ans = 0;
        for(int i = 0; i < s; ++i) {
            int flag = 1;
            for(int j = i; j < n + s; j+= s) {
                if(!ok[j]) {
                    flag = 0;
                    break;
                }
            }
            ans += flag;
        }
        if(ans == n + 1) ans = s;
        cout << ans << endl;
    }
    return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: