尺取(板子)

 

传送门

 

 
 
 
 
 
时限: 1000MS   内存限制: 65536K
提交总数: 34708   接受: 14379

描述

给出了N个正整数(10 <N <100 000)的序列,每个正整数均小于或等于10000,并给出了一个正整数S(S <100 000 000)。编写程序以查找该序列的连续元素的子序列的最小长度,其总和大于或等于S。

输入项

第一行是测试用例的数量。对于每个测试用例,程序必须从第一行读取数字N和S,并以一个间隔将其隔开。序列号在测试用例的第二行中给出,以间隔分隔。输入将以文件结尾结束。

输出量

对于每种情况,程序都必须将结果打印在输出文件的单独一行上。如果没有答案,则打印0。

样本输入

2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5

样本输出

2
3

 

 

 

 

 

#include<iostream>
#include<algorithm>
#include<cstring> 
using namespace std;
const int maxn=1e5+100; 
int a[maxn];
int n,m;
int main(){
    int t;
    cin>>t;
    while(t--){
        memset(a,0,sizeof(a));
        cin>>n>>m; 
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        int l=1,r=1;
        int sum=0;
        int ans=1e9;
        while(1){
            while(r<=n&&sum<m){//先找到一个合适的区间 
                sum+=a[r];
                r++;
            }
            if(sum<m){//先判断再更新结果 
                break;
            }
            ans = min(ans,r-l);
            //如果数组中都加完了之后还是小于sum,就不用再循环了
            sum-=a[l];
            l++; 
        }
        if(ans>n){
            ans=0;
        }
        cout<<ans<<endl;
    }
} 

 模板二:

 

这个模板二就是对于每一个i,向后找一个满足题意的j

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e6+100;
ll a[maxn];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        ll s=0; 
        for(int i=1;i<=n;i++){
            cin>>a[i];
            s+=a[i];
        }
        if(s<m){
            cout<<0<<endl;
            continue;
        }
        int ans=1e9;
        int j=1;
        ll sum=0;
        for(int i=1;i<=n;i++){
            sum+=a[i];
            while(sum-a[j]>=m){
                sum-=a[j];
                j++;
            }
            if(sum>=m){//3 4 5
                ans=min(ans,i-j+1);
            }
        }
        cout<<ans<<endl;
    }
}

 

posted @ 2020-11-14 23:00  lipu123  阅读(95)  评论(0编辑  收藏  举报