51nod 1065最小正子段和
题面:
题解:要求正字段中最小的,我们考虑先求出所有前缀和,对所有前缀和从小到大排序。下面说明最优答案一定出现在相邻的两个合法前缀中:
1.如果两个相邻前缀合法,那么[i,i+1]一定比[i,i+2]合法。
2.如果两个相邻的前缀相同,那么最优解可能存在于[i,i+2],当我们把相同值的id小的放到后面则[i,i+1]一定比[i,i+2]更优。
综上,最优解一定存在于相邻合法前缀中。
注意:答案初始化为第一个非负的前缀和。
#include#define ll long long using namespace std; const int N=5e4+100; ll a[N]; struct node { ll x; int id; }sum[N]; bool cmp(node a,node b) { if(a.x==b.x) return a.id>b.id; else return a.x<b.x; } int main() { //freopen("1.txt","r",stdin); int n; cin>>n; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } for(int i=1;i<=n;i++) { sum[i].x=sum[i-1].x+a[i]; sum[i].id=i; } sort(sum+1,sum+1+n,cmp); ll ans=1e18; for(int i=1;i<=n;i++) if(sum[i].x>0) { ans=sum[i].x; break; } for(int i=2;i<=n;i++) { if(sum[i].x>sum[i-1].x&&sum[i].id>sum[i-1].id) ans=min(ans,sum[i].x-sum[i-1].x); } cout< endl; return 0; }