CF1519 D. Maximum Sum of Products(双指针+思维)

16 篇文章 0 订阅
8 篇文章 0 订阅

D. Maximum Sum of Products

在这里插入图片描述
题目大意:
给定两个长为 n 的序列 a 和 b。你可以对 a 的一段区间翻转,也可以不翻转,要求翻转后 a 与 b 对应位置之积的和最大。即求下式的值最大:
∑ i = 1 n a i ∗ b i \sum_{i=1}^{n}a_i*b_i i=1naibi

思路:
首先考虑暴力,枚举每一个区间翻转,并进行求和,显然时间复杂度 O ( N 3 ) O(N^3) O(N3)会爆哎。

那不写除了暴力我还会个啥

其实呢,我们还可以得出一个小小的结论,就是每次交换后的答案所改变的值

假设我们交换 a i a_i ai a j a_j aj那么其改变量即为:
a i × b j + a j × b i − a i × b i − a j × b j a_i×b_j+a_j×b_i-a_i×b_i-a_j×b_j ai×bj+aj×biai×biaj×bj
即为
( a i − a j ) × ( b j − b i ) (a_i-a_j)×(b_j-b_i) (aiaj)×(bjbi)

那么此时我们脑海中就又出现了一个奇妙的想法,我们可不可以利用这个结论,通过扩张区间的操作来达到求出最大值呢

恶补考斯 耶斯(of course yes)

那么我们只需要枚举每一个区间的起点,但是区间有长度为奇数的,也有长度为偶数的,所以我们要分别枚举当区间以一个数为起点和以两个数为起点时的情况,累计求出改变的最大值,与初始值相加即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<sstream>
#include<queue>
#define fr for
#define pi 3.1415926535
#define me(a,b,c) memset(a,b,sizeof c)
#define cut cout
#define eps 0.00000001
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e6 + 10;
ll a[N];
map<int, int>mp;
ll b[N];
int main() {
	int n;
	cin >> n;
	ll sum = 0;
	fr(int i = 1; i <= n; i++)cin >> a[i];
	fr(int i = 1; i <= n; i++)cin >> b[i], sum += b[i]*a[i];
	ll h = 0;
	//起点为一个数(区间长度为奇数)
	fr(int i = 1; i <= n; i++) {
		ll h1 = 0;
		fr(int j = i, k = i; j >= 1 && k <= n; j--, k++) {
			h1 += (a[j] - a[k]) * (b[k] - b[j]);
			h = max(h, h1);
		}
	}
	//起点为两个数(区间长度为偶数)
	fr(int i = 1; i <= n; i++) {
		ll h2 = 0;
		fr(int j = i, k = i+1; j >= 1 && k <= n; j--, k++) {
			h2 += (a[j] - a[k]) * (b[k] - b[j]);
			h = max(h, h2);
		}
	}
	cut << sum + h << endl;
}


还有一种类似区间dp的做法,我蒻蒟本蒻不是太会
大概状态方程为 d p [ i ] [ j ] = d p [ i − 1 ] [ j + 1 ] + ( a i − a j ) × ( b j − b i ) dp[i][j]=dp[i-1][j+1]+(a_i-a_j)×(b_j-b_i) dp[i][j]=dp[i1][j+1]+(aiaj)×(bjbi)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值