51Nod - 1065 最小正子段和
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1065
知识点: (void)
解题思路:
先记录下序列的前缀和及对应的位置,然后根据前缀和从小到大排序,找出合理的两个前缀和之差最小的即可(所谓 “合理” 即是指大的前缀和所对应的位置肯定要在小的前缀和的后面,这样二者之差才是这两个位置之间的子段和)。有几个点需要注意:1、题目要求的是正子段和,所以除了让答案尽可能小之外还要大于0;2、要添加一个前缀和为0、位置为0的项,否则无法取序列中的单项。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef pair<ll,int> P; 5 const int maxn = 50000+4; 6 const ll inf=0x7fffffff; 7 ll a[maxn]; 8 P sum[maxn]; 9 int main(){ 10 int N; 11 scanf("%d",&N); 12 for(int i=1;i<=N;i++) scanf("%lld",&a[i]); 13 sum[0]=make_pair(0,0); 14 for(int i=1;i<=N;i++) sum[i]=make_pair(sum[i-1].first+a[i],i); 15 sort(sum,sum+N+1); 16 ll ans=inf; 17 for(int i=0;i<=N;i++){ 18 for(int j=i+1;j<=N;j++){ 19 if(sum[j].first-sum[i].first>=ans) break; 20 if(sum[j].second>sum[i].second&&sum[j].first-sum[i].first>0) 21 ans=sum[j].first-sum[i].first; 22 } 23 } 24 printf("%lld\n",ans); 25 26 return 0; 27 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”