一天,神犇和 LCR 在玩扑克牌。他们玩的是一种叫做“接竹竿”的游戏。
游戏规则是:一共有 张牌,每张牌上有一个花色 和一个点数 ,花色不超过 种。将这些牌依次放入一列牌的末端。若放入之前这列牌中已有与这张牌花色相同的牌,你可以选择将这张牌和任意一张花色相同的牌之间的所有牌全部取出队列(包括这两张牌本身),并得到与取出的所有牌点数和相同的分数。现在已知 LCR 把这 张牌放入队列的顺序,求她最多能得多少分。
输入顺序即为 LCR 放入队列的顺序。即, 表示第 张放入的牌的花色, 表示第 张放入的牌的点数。
请注意,如果你知道类似的纸牌游戏,请尤其仔细地阅读规则,以免因为理解题意错误而出现不必要的问题。
思路:根据第一个样例写转移方程式。
#include <bits/stdc++.h>
#define rg register
#define ine inline
#define lowbit(x) x&(~x+1)
#define rge(x) R[x]-L[x]+1
#define ChaBuDuo return//差不多
#define Dele 0;//得了
using namespace std;
typedef long long ll;
typedef unsigned int ut;
typedef const int coi;
typedef unsigned long long ul;
inline int rd() {
int ans = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
ans = (ans << 3) + (ans << 1) + ch - 48;
ch = getchar();
}
return ans * f;
}
coi lim = 1e6 + 2;
int n, k;
int val[lim], kind[lim];
int lastV[lim], previ[lim];
ll SV[lim];
ll dp[lim];
int main() {
n = rd(), k = rd();
for (int i = 1; i <= n; i++)
kind[i] = rd();
for (int i = 1; i <= n; i++)
val[i] = rd(), SV[i] = SV[i - 1] + val[i];
for (int i = 1; i <= n; i++) {
lastV[i] = previ[kind[i]];
previ[kind[i]] = i;
}
//一个需要记住的处理技巧!
//通过这样处理,lastV[i]就记录了上一个与第 i 个卡牌花色相同的卡牌的编号
//如果是0,那说明它确实事新来的
for (int i = 1; i <= n; i++) {
if (lastV[i])
dp[i] = max(dp[i - 1], max(dp[lastV[i] - 1] + SV[i] - SV[lastV[i] - 1], dp[lastV[i]] + SV[i] - SV[lastV[i]]));
else
dp[i] = dp[i - 1];
}
printf("%lld", dp[n]);
ChaBuDuo Dele
}