暂无链接
签到题
【问题描述】
这题很简单!
豆豆在玩一个扑克游戏。游戏规则如下:
一共有 n 张牌,每张牌上有一个花色 c 和一个点数 v,花色不超过 k 种。将这些牌依次放入一列牌的末端。若放入之前这列牌中已有与这张牌花色相同的牌,你可以选择将这张牌和任意一张花色相同的牌之间的所有牌全部取出队列(包括这两张牌本身),并得到与取出的所有牌点数和相同的分数。
现在已知这 n 张牌放入队列的顺序,豆豆想知道他最多能得多少分?
【输入格式】
第一行两个整数 n 和 k,表示牌数和花色数上限。
第二行 n 个整数 c1,c2…cn,ci表示放入的第 i 张牌的花色。
第三行 n 个整数 v1,v2…vn,vi表示放入的第 i 张牌的点数。
【输出格式】
输出一行一个整数,表示最多能得到的分数。
【输入样例】
7 3
1 2 1 2 3 2 3
1 2 1 2 3 2 3
【输出样例】
13
【数据范围】
本题采用捆绑测试,通过一个子任务下所有测试点才能获得该子任务得分。
对于 100%100%的数据:1≤n≤106,1≤ci≤k≤106,1≤vi≤109。1≤n≤106,1≤ci≤k≤106,1≤vi≤109。
子任务 1:7 分
1≤n,k≤15,ci=vi1≤n,k≤15,ci=vi
子任务 2:20 分
1≤n,k≤300,ci=vi1≤n,k≤300,ci=vi
子任务 3:17 分
1≤n,k≤30001≤n,k≤3000
子任务 4:23 分
1≤n,k≤2000001≤n,k≤200000
子任务 5:15 分
1≤n,k≤1000000,ci=vi1≤n,k≤1000000,ci=vi
子任务 6:18 分
1≤n,k≤10000001≤n,k≤1000000
题解
为写了个WAWA的正解然后每个SubtaskSubtask都错了几个的同学默哀。
dp[i]dp[i]表示1∼i1∼i的最优解,注意到转移时只可能由同种颜色转移过来,所以我们记录一下每种颜色的最优转移点在哪儿,在转移的时候顺带更新就可以做到O(n)O(n)。
代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e6+5;
int c[M],v[M],good[M],n,k;
long long dp[M],pre[M],ans;
void in()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)scanf("%d",&c[i]);
for(int i=1;i<=n;++i)scanf("%d",&v[i]),pre[i]=pre[i-1]+v[i];
}
void ac()
{
memset(good,-1,sizeof(good));
for(int i=1;i<=n;++i)
{
dp[i]=dp[i-1];
if(good[c[i]]<0){good[c[i]]=i-1;continue;}
dp[i]=max(dp[i],dp[good[c[i]]]+pre[i]-pre[good[c[i]]]);
if(dp[i-1]>dp[good[c[i]]]+pre[i-1]-pre[good[c[i]]])good[c[i]]=i-1;
}
for(int i=1;i<=n;++i)ans=max(ans,dp[i]);
printf("%lld",ans);
}
int main(){in();ac();}