官方题解:
这个题有很多O(n2)的算法,这里说一种:枚举每一个区间,在枚举区间的同时维护区间内的最小值和区间和,将最小值与P的大小进行比较,贪心地取最大值即可。注意若枚举到的区间是整个数组,则P的值是必须取的。 当然也存在O(n)的做法:从左往右处理出dp1[i]=max(a[i],dp1[i?1]+a[i]),同样从右往左处理出dp2[i]=max(a[i],dp2[i+1]+a[i]),再枚举要修改哪一个数,用两个数组更新答案即可。
我是用了两次dp,其实可以合成一个的,o(n2)的也是,每改一次dp一次,写的略丑。
#include<iostream> #include<cstring> #include<cstdio> #include<map> #include<cstring> #include<algorithm> #define INF 0x3f3f3f3f3f3F #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long llu; const int maxd=1000+10; //--------------------- ll a[maxd]; ll dp[2][maxd]; ll n,p; ll DP() { dp[0][0]=max(a[0],(ll)0); for(int i=1;i<n;++i) dp[0][i]=max((ll)0,(ll)dp[0][i-1]+a[i]); ll ans=a[0]; for(int i=1;i<n;++i){ dp[1][i]=dp[0][i-1]+a[i]; ans=max(ans,dp[1][i]); } return ans; } int main() { freopen("1.txt","r",stdin); int kase; scanf("%d",&kase); while(kase--) { scanf("%I64d%I64d",&n,&p); for(int i=0;i<n;++i) scanf("%I64d",&a[i]); ll ans=-1000000000001; for(int i=0;i<n;++i) { int tmp=a[i]; a[i]=p; ans=max(ans,DP()); a[i]=tmp; } printf("%I64d\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-11 16:09:35