码迷,mamicode.com
首页 > 其他好文 > 详细

11536 - Smallest Sub-Array(滑动窗口)

时间:2015-08-01 10:07:38      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:acm   uva   

该题其实就是lrj讲的滑动窗口的一个小小变形, 只不过这个窗口的大小是可变的 。  具体方法其实和例题Shuffle类似,用首尾两个指针维护窗口,用一个数组cnt记录1~k中每个数字在窗口中出现的次数,用一个变量c记录窗口中只出现了一次的数字的个数 。   这样只要c == k 这就是一个满足条件的答案,取最小答案即可 。

由于每个元素都只插入删除一次,所以时间复杂度为O(n)。

该算法还有一个名字叫“取尺法” ,特点是处理一段长度未知的连续区间,通过反复地推进区间的开头和末尾 ,直到得出答案的方法 。

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000000 + 10;
int T,n,m,k,Case = 0,a[maxn],cnt[maxn];
map<int,int> p;
vector<int> g[105];
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d%d",&n,&m,&k);
        memset(cnt,0,sizeof(cnt));
        a[1] = 1; a[2] = 2; a[3] = 3;
        if(n>3) for(int i=4;i<=n;i++) {
            a[i] = (a[i-1]+a[i-2]+a[i-3])%m + 1;
        }
        int ans = 2000000000;
        int rear = 0,last = 1,c = 0;
        while(true) {
            if(c == k) {
                cnt[a[last]] -- ;
                if(cnt[a[last]] == 0 && a[last] <= k) c--;
                last++;
                if(c == k) ans = min(ans , rear - last + 1);
            }
            else {
                rear ++;
                if(rear > n) break;
                cnt[a[rear]]++;
                if(cnt[a[rear]] == 1 && a[rear] <= k) c++;

                if(c == k) ans = min(ans , rear - last + 1);

            }
        }
        printf("Case %d: ",++Case);
        if(ans != 2000000000) printf("%d\n",ans);
        else printf("sequence nai\n");
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

11536 - Smallest Sub-Array(滑动窗口)

标签:acm   uva   

原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/47176111

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!