题目地址:http://vjudge.net/problem/UVALive-2678
类似于一种滑动窗口
i~j始终维护<=S的最短子序列
先j向右扫描,i不动,直到sum=∑a[k] (i<=k<=j) >=S;
然后i向右扫描,直到刚好sum>=S,更新答案ans=min(ans,j-i)
算法复杂度O(n)
#include <bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=a;i<=(b);++i)
#define REPD(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))
const int maxn=100000+5,INF=0x3f3f3f3f;
int a[maxn];
int main(int argc, char const *argv[])
{int N,S;while(scanf("%d%d",&N,&S)==2){REP(i,1,N) scanf("%d",&a[i]);int i=0,ans=INF,sum=0;REP(j,1,N){sum+=a[j];if(sum<=S) continue;while(sum-a[i+1]>=S) sum-=a[++i]; //sum+a[j]>=S;ans=min(ans,j-i);}printf("%d\n", ans==INF?0:ans);}return 0;
}