1. 程式人生 > >Welcome to JRX2015U43's blog!

Welcome to JRX2015U43's blog!

【英文題目】

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.

【簡要翻譯】

給出一個序列,求區間和大於或者等於S的最短區間長度,要求O(n)做法。

【分析】

法一:3重迴圈暴力列舉

法二:用字首和去掉法一的1個迴圈,變成2重

法三:觀察到序列非負即字首和單調不減,可以列舉左端點再二分找到右端點,O(nlogn)的複雜度。

法四(我最先想到的方法,前3個都沒想到):兩個指標確定左右端點,則隨著l指標單調遞增,r指標一定不會遞減。這是顯然的:l指標右移之後當前區間和必然減小,那麼就只能通過右移r指標補充,否則就與原來的[l,r]恰好滿足條件矛盾(即[l,r-1]也滿足)。

法四程式碼(一開始沒看到題目說無解輸出0,WA了好幾發):

​
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+5;
int a[N];
int n,sum;
void work(){
	int ans=n,l=1,r=1,x=0;
	for (int i=1;i<=n;i++) x+=a[i];
	if (x<sum) {printf("0\n");return;} else x=a[1];
	while (l<=n){
	    if (x>=sum) ans=min(ans,r-l+1);
	    x-=a[l++];
	    while (x<sum && r<n) x+=a[++r];
	    if (r>=n && x<sum) break;
	}
	printf("%d\n",ans);
}
int main(){
  int T;
  scanf("%d",&T);
  while (T--){
	  scanf("%d%d",&n,&sum);
	  for (int i=1;i<=n;i++) scanf("%d",&a[i]);
  	  work();
  }
}
//縮排好像出鍋了,將就著看吧。。。