Educational Codeforces Round 63 D题

类似的kadane算法。
我们假设需要,最大连续子列和。
那么用dp[i]来表示,第i位时,最大连续子列和。
意思为,如果这个序列是以i结尾的话,那么最大值位多少。
那么就有两种办法,一种是要这个数字,一种是单开一个。
就有这样的算法出现
sum=max(sum+a[i],a[i]).
ans=max(ans,sum)。

sum即i的最大前缀和(注意是要找连续的,所以相当于是i,i-1,i-2,i-3…,i-n+1(n<i)的和)
所以这道题著需要稍微变化一下。
我们相当于要维护两端区间,一个是需要乘以x的,一个时正常的连续加和。
假设sum表示以i结尾的最大连续正常的加和。
那么对于需要乘以x的区间来说。
以sum2表示,以i结尾的区间,且a[i]*x的区间和。
sum2就可以这样更新出来,sum2=max(sum2,sum),sum2=max(sum2+a[i]*x,a[i]*x);
第二个语句就是正常更新,第一句话的意思就是,sum2可能从两个地方转移而来,前一个可能没有乘以x,或者前一个乘以了x。

感觉此题到这里就完了,所以wa了两发。

后来仔细思考一下就发现了问题,我们的sum这个函数其实并没有转移,他也是可能从两个地方来转移的,一个是前一个乘以了,一个是前一个没有乘,所以同时也需要不断更新sum,但这里如果直接写max函数并不是特别好写,所以单开一个sum3来表示,转移过的最后一位没有乘以x的和。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
	char ch = getchar(); int x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
ll n, x, a[300005], sum = 0, sum1 = 0, sum2 = 0, ans = 0;
int main()
{
	cin >> n >> x;
	up(i, 0, n) {
		scanf("%lld", &a[i]);
		sum1 = max(sum, sum1);
		sum = max(a[i], sum + a[i]);
		if (sum < 0)sum = 0;
		sum1 = max(x*a[i], sum1 + x * a[i]);
		sum2 = max(sum2 + a[i], sum1);
		ans = max(ans, sum2);
	}
	cout << ans;
}

猜你喜欢

转载自blog.csdn.net/weixin_44019404/article/details/89517669
今日推荐