1. 程式人生 > 實用技巧 >51nod 1065最小正子段和

51nod 1065最小正子段和

題面:

題解:要求正欄位中最小的,我們考慮先求出所有字首和,對所有字首和從小到大排序。下面說明最優答案一定出現在相鄰的兩個合法字首中:

1.如果兩個相鄰前綴合法,那麼[i,i+1]一定比[i,i+2]合法。

2.如果兩個相鄰的字首相同,那麼最優解可能存在於[i,i+2],當我們把相同值的id小的放到後面則[i,i+1]一定比[i,i+2]更優。

綜上,最優解一定存在於相鄰合法字首中。

注意:答案初始化為第一個非負的字首和。

#include<bits/stdc++.h>
#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<<ans<<endl; return 0; }
View Code