[ABC267D] Index × A(Not Continuous ver.) Solution
目录更好的阅读体验戳此进入
题面
求序列 $ A_n $ 的长度为 $ m $ 的最大权值子序列 $ B_m $,定义序列 $ B_m $ 的权值为 $ \sum_{i = 1}^m i \times B_i $。输出最大权值。
Solution
提供一种不同的思路。
一种显而易见的思路就是考虑 $ i $ 是否选,则 DP 是 $ \texttt{2D0D} $ 的,这里提供一种 $ \texttt{2D1D} \rightarrow \texttt{2D0D} $ 的做法。
我们考虑一个类似 LIS 的做法,考虑令 $ dp(i, j) $ 表示长度为 $ i $ 的以 $ j $ 结尾的子序列的最大权值,转移显然为:
\[dp(i, j) = \max_{k = 1}^{j - 1} dp(i - 1, k) + i \times A_j \]即考虑从之前的某一个最优子序列拼过来。
这个东西十分显然可以简单写一个前缀和优化,最终复杂度 $ O(n^2) $。
初始值即为 $ dp(0, i) = 0 $,注意初始时需要将除了 $ 0 $ 之外的所有 $ sum $ 都初始化为 $ -\infty $,否则因为负权值可能存在一些不正确的转移。
Code
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
using namespace std;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;
template < typename T = int >
inline T read(void);
int N, M;
ll A[2100];
ll dp[2100][2100];
ll sum_mx[2100][2100];
int main(){
memset(sum_mx, 0xc0, sizeof sum_mx);
N = read(), M = read();
for(int i = 0; i <= N; ++i)sum_mx[0][i] = 0;
for(int i = 1; i <= N; ++i)A[i] = read();
for(int i = 1; i <= M; ++i)
for(int j = 1; j <= N; ++j)
dp[i][j] = sum_mx[i - 1][j - 1] + A[j] * i,
sum_mx[i][j] = max(sum_mx[i][j - 1], dp[i][j]);
printf("%lld\n", sum_mx[M][N]);
fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
template < typename T >
inline T read(void){
T ret(0);
int flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
UPD
update-2023_01_14 初稿
标签:Index,int,题解,sum,Continuous,ret,2100,dp,define From: https://www.cnblogs.com/tsawke/p/17124333.html