CF1580D Subsequence

CF1580D Subsequence

题目大意:

Alice 有一个长度为 \(n\) 的整数序列 \(a\),所有元素都是不同的。她将选择一个长度为 \(m\)\(a\) 的子序列,并将一个子序列 \(a_{b1},a_{b2},...,a_{bm}\) 的价值定义为

\(\sum_{i = 1}^m (m \cdot a_{b_i}) - \sum_{i = 1}^m \sum_{j = 1}^m f(\min(b_i, b_j), \max(b_i, b_j))\)

其中 \(f(i,j)\) 表示 \(\min(a_i,a_{i+1},..., a_j)\)

Alice 希望你能帮助她将她所选择的子序列的价值最大化。

思路:

考虑 尘封已久的 DP。

\(dp_{l,r,k}\) 为区间 \([l,r]\) 中,选择 \(k\) 个值作为子序列的最大值。下令 \(pos\) 为区间 \([l,r]\) 中最小的位置。

易得:

\[dp_{l,pos-1,x} + dp_{pos+1,r,k-x} - 2 \times x \times (k - x) \times a_{pos} \rightarrow dp_{l,r,k}\\ dp_{l,pos-1,x} + dp_{pos+1,r,k-x} + m \times a_{pos} - (2 \times (x + 1) \times (k - x + 1) - 1) \times a_{pos} \rightarrow dp_{l,r,k+1} \]

然后就可以笛卡尔树上DP啦!

代码中函数 Solve(l,r) 返回 vector 类型的 res,其中:res[i] 表示题解中 \(dp_{l,r,i}\) 的值。

代码:

#include <bits/stdc++.h>
#define ll long long
#define INF 9223372036854775807
#define Maxn 4005

using namespace std;

ll n, m, a[Maxn];

vector<ll> Solve(ll l, ll r) {
//	cerr << l << " " << r << "\n";
	vector<ll> res(r - l + 2, -INF);
	res[0] = 0;
	if (l > r) {
//		cerr << "IN\n";
		return res;
	}
	
	ll minl = INF, pos = l - 1;
	for (ll i = l; i <= r; i ++) {
		if (a[i] < minl) { pos = i; }
		minl = min(minl, a[i]);
	}
	
	vector<ll> lft = Solve(l, pos - 1), rgt = Solve(pos + 1, r);
//	cerr << l << " " << r << " : " << lft.size() << " " << rgt.size() << "\n";
	for (int i = 0; i < (int)lft.size(); i ++) {
		for (int j = 0; j < (int)rgt.size(); j ++) {
			res[i + j] = max(res[i + j], lft[i] + rgt[j] - 2 * i * j * a[pos]);
			res[i + j + 1] = max(res[i + j + 1], lft[i] + rgt[j] + m * a[pos] - (2 * (i + 1) * (j + 1) - 1) * a[pos]);
		}
	} return res;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin >> n >> m;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
	} cout << Solve(1, n)[m];
	return 0;
}
posted @ 2024-11-24 17:05  BLM-dolphin  阅读(29)  评论(0)    收藏  举报