题目
n(n<=2e5)个球在同一行,第i个球颜色是ci(ci<=n),值是vi(vi<=1e9)
恰好移走k(k<=500)个球,剩下的球不改变顺序依次接上,
在满足剩下的球相邻两个球的颜色都不同的情况下,最大化剩余球的价值和
输出这个最大的价值和
如果没法满足颜色都不同的条件,输出-1
思路来源
赛后又仔细想了想就会了
题解
暴力是O(n*k*k)的,枚举当前颜色是什么,枚举上一个颜色是什么
但是仔细观察发现,实际前驱颜色只需要两种,即产生最大贡献的颜色,产生次大贡献的颜色
dp[i][j][2],其中dp[i][j][0]表示前i个删了j个后最大(和,颜色)
dp[i][j][1]表示颜色和最大严格不同(也就是和dp[i][j][0]的颜色不同)时次大的(和,颜色)
枚举转移即可,用一个值更新最大值,最大值没更新可以尝试更新次大值,
同时需要保证转移后,次大的颜色仍然不能和最大的颜色相同
暴力讨论倒是也可以,优雅一点的写法是和最大值比如果可更新就swap,
然后就可以用换下来的值和次大值比了
代码
// Problem: E - Colorful Subsequence
// Contest: AtCoder - Monoxer Programming Contest 2024(AtCoder Beginner Contest 345)
// URL: https://atcoder.jp/contests/abc345/tasks/abc345_e
// Memory Limit: 1024 MB
// Time Limit: 5000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=2e5+10,K=505;
const ll INF=1e16;
P dp[2][K][2];//dp[i][j][k]表示前i个删了j个后最大(和,颜色) 颜色和最大严格不同时次大的(和,颜色)
int n,k,c[N],v[N];
int main(){
sci(n),sci(k);
rep(i,1,n){
sci(c[i]);
sci(v[i]);
}
dp[0][0][0]=P(0,0);
dp[0][0][1]=P(-1,0);
rep(i,0,n-1){
int f=i&1,g=f^1,up=min(i,k);
//printf("i:%d f:%d g:%d up:%d\n",i,f,g,up);
rep(j,0,up+1){
dp[g][j][0]=P(-1,0);
dp[g][j][1]=P(-1,0);
}
rep(j,0,up){
rep(l,0,1){
ll w=dp[f][j][l].fi;
int col=dp[f][j][l].se;
if(w==-1)continue;
//printf("i:%d f:%d j:%d l:%d w:%lld col:%d\n",i,f,j,l,w,col);
if(j+1<=k){//删,次数未超
P cur=P(w,col);
rep(x,0,1){
if(x==1 && cur.se==dp[g][j+1][0].se)continue;//颜色严格不同
if(cur.fi>=dp[g][j+1][x].fi){
swap(dp[g][j+1][x],cur);
}
}
}
if(col!=c[i+1]){//不删,尾色不同
P cur=P(w+v[i+1],c[i+1]);
rep(x,0,1){
if(x==1 && cur.se==dp[g][j][0].se)continue;//颜色严格不同
if(cur.fi>=dp[g][j][x].fi){
swap(dp[g][j][x],cur);
}
}
}
}
}
}
ptlle(dp[n&1][k][0].fi);
return 0;
}