POJ-3061 Subsequence(前缀和+二分/尺取)

版权声明:转载请标明出处哦 https://blog.csdn.net/PleasantlY1/article/details/82316659

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;
}

猜你喜欢

转载自blog.csdn.net/PleasantlY1/article/details/82316659