V字钩爪
题目链接
我们首先的想法是想把相互独立的点分开,把会产生影响的点放一起,那么哪些是会产生影响的点呢。这里是相隔
k
k
k 即可产生相互影响,那实际上就是处在
k
k
k 的一个同余系下的点就是会产生影响的,我们可以把处在同一同余系下的点如下代码拆出来扔进一个
v
e
c
t
o
r
vector
vector 里面去,于是我们就可以独立考虑每个同余系的答案。
for (int i = 1; i <= n; ++i) {
g[i % k].push_back(a[i]);
}
那么对于同一个 i % k i\% k i%k (同余系),他们的值如何算呢,实际上他们的限制就是一次操作只能取相邻的两个点,那么我们可以通过 d p dp dp 解决这个问题。
我们设 d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1] 为考虑到了第 i i i 个物品(下标从 0 0 0 开始),且第 i i i 个物品不取 ( 0 ) (0) (0) 或者取 ( 1 ) (1) (1) 情况下所能得到的最大值。
我们这里设第
i
i
i 个物品价值为
v
a
l
[
i
]
val[i]
val[i] ,且当前同余系下共有
m
m
m 个物品,那么我们有:
d
p
[
0
]
[
0
]
=
d
p
[
0
]
[
1
]
=
0
dp[0][0]=dp[0][1]=0
dp[0][0]=dp[0][1]=0
d
p
[
i
]
[
0
]
=
m
a
x
(
d
p
[
i
−
1
]
[
0
]
,
d
p
[
i
−
1
]
[
1
]
)
(
i
>
0
)
dp[i][0] = max(dp[i - 1][0], dp[i-1][1])\ (i>0)
dp[i][0]=max(dp[i−1][0],dp[i−1][1]) (i>0)
d
p
[
i
]
[
0
]
=
d
p
[
i
−
1
]
[
0
]
+
v
a
l
[
i
−
1
]
+
v
a
l
[
i
]
(
i
>
0
)
dp[i][0] = dp[i - 1][0]+val[i-1]+val[i]\ (i>0)
dp[i][0]=dp[i−1][0]+val[i−1]+val[i] (i>0)
最终 m a x ( d p [ m − 1 ] [ 0 ] , d p [ m − 1 ] [ 1 ] ) max(dp[m-1][0], dp[m-1][1]) max(dp[m−1][0],dp[m−1][1]) 为这一同余系的答案,最后我们把每种情况求和即是最终答案。
#include <bits/stdc++.h>
#define lson (rt<<1)
#define rson ((rt<<1)|1)
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int n, k, a[N], vis[N];
ll dp[N][2];
vector<int> g[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; ++i) {
g[i % k].push_back(a[i]);
}
ll ans = 0;
for (int i = 0; i < k; ++i) {
if (g[i].empty()) continue;
int m = (int)g[i].size();
for (int j = 1; j < m; ++j) {
dp[j][0] = max(dp[j - 1][0], dp[j - 1][1]);
dp[j][1] = dp[j - 1][0] + g[i][j] + g[i][j - 1];
}
ans += max(dp[m - 1][0], dp[m - 1][1]);
}
cout << ans << endl;
}