最小正子段和 貪心
阿新 • • 發佈:2017-10-04
復雜度 max 限制 需要 16px size typedef urn span
最小正子段和
基準時間限制:1 秒 空間限制:131072 KB
N個整數組成的序列a[1],a[2],a[3],…,a[n],從中選出一個子序列(a[i],a[i+1],…a[j]),使這個子序列的和>0,並且這個和是所有和>0的子序列中最小的。
例如:4,-1,5,-2,-1,2,6,-2。-1,5,-2,-1,序列和為1,是最小的。
Input
第1行:整數序列的長度N(2 <= N <= 50000) 第2 - N+1行:N個整數Output
輸出最小正子段和。Input示例
8 4 -1 5 -2 -1 2 6 -2Output示例
1
思路:先求出前綴和,然後對前綴和進行排序,排序後求出最大的相鄰前綴和之差,並且要滿足:相鄰前綴和在排序前的位置是遞增的。輸出這個答案即可
簡單地考慮一下這個算法的正確性:如果沒有進行排序,求前後兩個前綴和的差的最大值是沒有錯的,暴力計算需要O(n2)的復雜度,
排序後,設此時的前綴和為sum[i],每個前綴和對應排序前的位置為p[i],相鄰的前綴和如果滿足更新條件,即sum[p[i]]>sum[p[i-1]]&&p[i]>p[i-1],
假設存在一個x<i-1也滿足相同條件,我們令p[i]>p[x]>p[i-1]且sum[p[i]]-sum[p[x]]<sum[p[i]]-sum[p[x]],
即存在與第i個前綴和不相鄰的前綴和sum[p[x]],第i個前綴和與第x個前綴和的差值要優於與第i-1的差值,那麽就有sum[p[x]]>sum[p[i-1]],但是x<i-1,和排序結果是矛盾的,所以不存在x獲得排序後第i個前綴和的最優解,即最優解一定是排序後相鄰前綴和的差值。
AC代碼:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int MAXN=5e4+10; 8 const LL INF=1e15+10; 9 LL sum[MAXN]; 10 int p[MAXN]; 11 bool cmp(inta, int b){ 12 return sum[a]<sum[b]; 13 } 14 int main() 15 { 16 int n,m; 17 sum[0]=0; 18 scanf("%d", &n); 19 for(int i=0;i<=n;i++) p[i]=i; 20 for(int i=1;i<=n;i++){ 21 scanf("%d", &m); 22 sum[i]=sum[i-1]+m; 23 } 24 sort(p, p+n+1, cmp); 25 LL res=INF; 26 for(int i=1;i<=n;i++){ 27 if(sum[p[i]]-sum[p[i-1]]>0&&p[i]>p[i-1]) 28 res=min(res, sum[p[i]]-sum[p[i-1]]); 29 } 30 printf("%lld\n", res); 31 }
最小正子段和 貪心