POJ-3061 Subsequence(字首和+二分/尺取)

大白QQly成長日記發表於2018-09-02

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.

Input

The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.

Output

For each the case the program has to print the result on separate line of the output file.if no answer, print 0.

Sample Input

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

Sample Output

2
3

題目大意:給出n個數和一個m,求這n個數中長度最小的連續序列,要求這個最小序列和大於等於m。

思路:明明是尺取專題第一反應是用字首來做.....還真的能做........

字首和+二分:在輸入的時候進行記錄字首和,然後以m為基準二分查詢。複雜度nlogn

尺取:遍歷,先求一個大於等於m的序列,標記左右端點,依次移動左端點,再根據左端點移動有端點。複雜度n

字首和+二分做法:

#include<set>
#include<map>
#include<list>
#include<deque>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<stdio.h>
#include<sstream>
#include<stdlib.h>
#include<string.h>
//#include<ext/rope>
#include<iostream>
#include<algorithm>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define max(a,b)  a>b?a:b
#define min(a,b)  a<b?a:b
#define LL long long 
#define swap(a,b) {int t=a;a=b;b=t} 
using namespace std;
//using namespace __gnu_cxx;
LL  p[100010];
int n,m,s,t,b,l,r;
int main()
{
    scanf("%d",&t);
	while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(p,0,sizeof(p));
        per(i,1,n)
        {
            scanf("%d",&b);
            p[i]=p[i-1]+b;
        }
        s=INF;
        per(i,1,n)
		{
            l=i;r=n;
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(p[mid]-p[i-1]>=m)//二分查詢m值 
                {
                    s=min(s,mid-i+1);
                    r=mid-1;
                }else{
                    l=mid+1;
                }
            }
        }
        if(s==INF) printf("0\n");
        else printf("%d\n",s);
    }
    return 0;
}

尺取做法:

#include<set>
#include<map>
#include<list>
#include<deque>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<stdio.h>
#include<sstream>
#include<stdlib.h>
#include<string.h>
//#include<ext/rope>
#include<iostream>
#include<algorithm>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define max(a,b)  a>b?a:b
#define min(a,b)  a<b?a:b
#define LL long long 
#define swap(a,b) {int t=a;a=b;b=t} 
using namespace std;
//using namespace __gnu_cxx;
int p[100010];
int main() 
{
    int T,n,m;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        per(i,1,n) scanf("%d",&p[i]);
        int z=n+1;
        int k=0,s=1,t=1;
        while(1)
        {
            while(t<=n&&k<m) 
			{
                k+=p[t];
                t++;
            }//根據左端移動右端
            if(k<m) break;
            z=min(z,t-s);
            k-=p[s++];//cout<<k<<"*"<<endl;
        }
        if(z<=n) printf("%d\n",z);
        else printf("0\n");
    }
    return 0;
}

 

相關文章