题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5280
题意:将一个长度为n的数组,将里面某一个数改为p,使改变后最大子段和最大。
题解:dp[i]=max(dp[i-1)+a[i],a[i]),表示以第 i 个数结束的最大子段和,时间复杂度为O(n)。
1)由于n<=1000,可以暴力解决,将每一个数都依次改为p,求出最大的子段和,再去这些最大子段和中最大的,时间复杂度为O(n*n);
#include <iostream> #include <cmath> using namespace std; long long a[1005]; long long dp[1005]; int main() { int t; cin>>t; while(t--) { int n,p,temp; cin>>n>>p; for(int i=1;i<=n;i++) cin>>a[i]; long long maxn=a[1]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { temp=a[i]; a[i]=p; dp[j]=max(dp[j-1]+a[j],a[j]); maxn=max(maxn,dp[j]); a[i]=temp; } cout<<maxn<<endl; } return 0; }
2)l[i]以 i 个数结束的最大字段和,r[i]为以第 i 个数开始的最大字段和;如果a[i]改为p在这个最大的连续字段和中,那么这段字段和为max(l[i-1],0ll)+max(r[i+1],0ll)+p;
若果a[i]-->p不连续字段和中,就只要对l[1....n-1]和r[n.....2]遍历一遍就行;
#include <iostream> #include <cmath> using namespace std; long long a[1005]; long long l[1005]; long long r[1005]; int main() { int t; cin>>t; while(t--) { int n,p; cin>>n>>p; l[0]=r[n+1]=0; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) l[i]=max(a[i],a[i]+l[i-1]); for(int i=n;i>0;i--) r[i]=max(a[i],r[i+1]+a[i]); long long maxn=a[1]; for(int i=1;i<=n;i++) maxn=max(maxn,max(l[i-1],0ll)+max(r[i+1],0ll)+p); for(int i=1;i<n;i++) maxn=max(maxn,l[i]); for(int i=n;i>1;i--) maxn=max(maxn,r[i]); cout<<maxn<<endl; } return 0; }
hdu 5280 Senior's Array(最大子段和)
时间: 2024-12-24 08:58:55