UVA:11536 Smallest Sub-Array(尺取法)

题意:求包含数字1——K的最小区间长度。

思路:尺取法。维护一个区间,右端点扩张一直到区间满足条件,此时更新答案,然后左端点逐步左移。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <stack>
#include <unordered_map>
#include <queue>
using namespace std;
const int maxn=1000005;
int a[maxn];
int solve(const vector<int> &v,int k)
{
    int ans=v.size()+1,st=0,ed=0;
    unordered_map<int,int> pos;
    int sz=0;
    while(true)
    {
        while(ed<v.size()&&sz<k)
        {
            if(1<=v[ed]&&v[ed]<=k)
            {
                if(pos.find(v[ed])==pos.end()||pos[v[ed]]<st) ++sz;
                pos[v[ed]]=ed;
            }
            ++ed;
        }
        if(sz<k) break;
        ans=min(ans,ed-st);
        if(1<=v[st]&&v[st]<=k)
        {
            if(pos[v[st]]==st)
                --sz;
        }
        ++st;
    }
    return ans;
}

int main()
{
    int T,kase=0;
    scanf("%d",&T);
    a[1]=1,a[2]=2,a[3]=3;
    while(T--)
    {
        int N,M,K;
        scanf("%d%d%d",&N,&M,&K);
        for(int i=4; i<=N; ++i)
            a[i]=(a[i-1]+a[i-2]+a[i-3])%M+1;
        vector<int> v(a+1,a+N+1);
        int ans=solve(v,K);
        printf("Case %d: ",++kase);
        if(ans==v.size()+1) puts("sequence nai");
        else printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(尺取法)