Educational Codeforces Round 63 (Rated for Div. 2) D. Beautiful Array(动态规划.递推)

传送门

题意:

  给你一个包含 n 个元素的序列 a[];

  定义序列 a[] 的 beauty 为序列 a[] 的连续区间的加和最大值,如果全为负数,则 beauty = 0;

  例如:

  a[] = {10, -5, 10, -4, 1} ;

  beauty = 15;( 10+(-5)+10 )

  a[] = {-3, -5, -1};

  beauty = 0;( 不取 )

  给你一个整数 x,你可以将序列 a[] 的任意子序列 a[ l , r ]*x(即 a[l]=a[l]*x,a[l+1]=a[l+1]*x,.....,a[r]=a[r]*x);

  当然,也可以不执行这个操作;

  求 beauty 的最大值;

思路:

  一看到这道题,第一反应就贪过去了;

  贪了好大一会,交了几发程序,全部 "Wrong answer on test 5";

  看了一眼他人的AC代码,看到了 dp 数组,然后,想了好久好久的动态规划解法;

  wa 了改,改了 wa,终于,在下午临近吃饭的时候,AC了(大佬轻点虐)

  

  假设修改的区间为[ L,R ]

  那么,对于∀i∈[1,n], i = L or L < i < R or i = R;

  定义 dp[ i ][ j ],含义如下:

  j = 0 : i 作为修改区间的起始位置,从 i 开始向左能形成的最大区间和;

  j = 1 : i 作为修改区间的中间位置,从 i 开始向左能形成的最大区间和;

  j = 2 : i 作为修改区间的终点位置,i 可以形成的最大区间和;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define INFll 0x3f3f3f3f3f3f3f3f
 6 #define ll long long
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 const int maxn=3e5+50;
 9 
10 int n,x;
11 ll a[maxn];
12 /**
13     在做*x的操作下
14     dp[i][0]:i位置为修改区间的开始
15     dp[i][1]:i位置为修改区间的中间部分
16     dp[i][2]:i位置为修改区间的结尾
17 */
18 ll dp[maxn][3];
19 /**
20     在不做*x的操作下
21     maxL[i]:以i开始的向左能形成的最大的区间和
22     maxR[i]:以i开始的向右能形成的最大的区间和
23 */
24 ll maxL[maxn];
25 ll maxR[maxn];
26 
27 ll Solve()
28 {
29     maxL[0]=-INFll;
30     for(int i=1;i <= n;++i)
31         maxL[i]=max(maxL[i-1]+a[i],a[i]);
32     maxR[n+1]=-INFll;
33     for(int i=n;i >= 1;--i)
34         maxR[i]=max(maxR[i+1]+a[i],a[i]);
35 
36     dp[0][0]=dp[0][1]=0;
37     for(int i=1;i <= n;++i)
38     {
39         dp[i][0]=x*a[i]+(maxL[i-1] > 0 ? maxL[i-1]:0);
40         dp[i][1]=max(dp[i-1][0],dp[i-1][1])+x*a[i];
41         dp[i][2]=max(dp[i][0],dp[i][1])+(maxR[i+1] > 0 ? maxR[i+1]:0);
42     }
43 
44     ll ans=0;
45     for(int i=1;i <= n;++i)
46         ans=max(max(ans,maxL[i]),dp[i][2]);
47 
48     return ans;
49 }
50 int main()
51 {
52     while(~scanf("%d%d",&n,&x))
53     {
54         for(int i=1;i <= n;++i)
55             scanf("%lld",a+i);
56         printf("%I64d\n",Solve());
57     }
58 }
View Code

巨巨代码(额外增加点我的注释)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define mem(a,b) memset(a,b,sizeof(a))
 4 #define ll long long
 5 
 6 int n,x;
 7 ll a[300030];
 8 ll dp[300030][3];
 9 
10 int main()
11 {
12     ll ans=0;
13     cin>>n>>x;
14     for(int i=1;i<=n;++i)
15         cin>>a[i];
16 
17     mem(dp[0],0);
18     /**
19         dp[i][0]:[1,i]未使用*x所形成的最大区间和
20         dp[i][1]:[L,i-1]使用*x,并且i也使用*x所形成的最大区间和
21         dp[i][2]:[L,i-1]使用*x,但是i不使用*x所形成的最大区间和
22     */
23     for(int i=1;i<=n;++i)
24     {
25         dp[i][0]=a[i]+(dp[i-1][0] > 0 ? dp[i-1][0]:0);
26         dp[i][1]=max(0LL,max(dp[i-1][0],dp[i-1][1]))+a[i]*x;
27         dp[i][2]=max(0LL,max(dp[i-1][1],dp[i-1][2]))+a[i];
28         for(int j=0;j<3;++j)//三者去最值
29             ans=max(ans,dp[i][j]);
30     }
31     cout<<ans<<endl;
32 
33     return 0;
34 }
View Code

猜你喜欢

转载自www.cnblogs.com/violet-acmer/p/10758836.html