Welcome to JRX2015U43's blog!
阿新 • • 發佈:2018-12-16
【英文題目】
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(); } } //縮排好像出鍋了,將就著看吧。。。