尺取法

对数组保存一组下标(起点,终点),然后根据实际情况交替推进两个端点直到得出答案。

#include<iostream>
using namespace std;
int N,S,K;
int a[100005];
int main()
{
    cin>>K;
    while(K--)
    {
        cin>>N>>S;
        for(int i=0;i<N;i++)
        {
            cin>>a[i];
        }
        int res=N+1;
        //尺取法
        int s=0,t=0,sum=0;
        for(;;)
        {
            while(t<N&&sum<S) sum+=a[t++];
            if(sum<S) break;
            res=min(res,t-s);
            sum-=a[s++];
        }
        if(res>N) cout<<0<<endl;
        else cout<<res<<endl;
    }
}
poj3061

#include<iostream>
#include<stdio.h>
#include<set>
#include<map>
using namespace std;
int P;
int a[1000005];
int main()
{
    scanf("%d",&P);
    //所有知识点
    set<int> se;
    //知识点->出现次数 映射
    map<int,int> m;
    for(int i=0;i<P;i++)
    {
        scanf("%d",&a[i]);
        se.insert(a[i]);
    }
    //知识点个数
    int n=se.size();

    //尺取法
    int s=0,t=0,num=0,ans=P;
    while(true)
    {
        while(t<P&&num<n)
        {
            if(m[a[t++]]++==0) num++;
        }
        if(num<n) break;
        ans=min(ans,t-s);
        if(--m[a[s++]]==0) num--;
    }
    printf("%d",ans);
}
poj3320
原文地址:https://www.cnblogs.com/wangkaipeng/p/6486450.html