大体思路如下
找出所有连续相同颜色区间,将每个区间的最大留下,称为第一轮筛选,如果第一轮删掉的个数超过上限,说明无解。
若第一轮删掉的不足以达到上限,则进行第二轮筛选,在不会生成新的连续区间的情况下尽可能删除小权重的球
代码如下
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n, k;//如题
ll a[1000015], b[1000015];//a颜色编号、b权重
ll c[1000015], d[1000015];//c连续颜色区间左端点,d右端点
ll m[1000015];//每个连续颜色区间权重的最大值
ll co[1000015];//每个连续颜色区间的颜色编号
ll cnt;//连续颜色区间数量 ,同时易得其为第二轮筛选时球的个数
struct sss {
ll vol, to;//vol权重,to指针指向aaa[]
} aa[1000015];//第二轮筛选的数组
bool cmp(sss a, sss b) {
return a.vol<b.vol;
}
ll aaa[1000015];//记忆数组 ,存储颜色编号与排序
ll answer;//答案
ll asdf;//表示第二轮筛选了几个
int main() {
cin>>n>>k;
for(ll i=1; i<=n; i++) {
cin>>a[i]>>b[i];
if(a[i]==a[i-1]) {
d[cnt]=i;
m[cnt]=max(m[cnt],b[i]);//找每个区间的最大权重球
} else {
cnt++;
c[cnt]=d[cnt]=i;
m[cnt]=b[i];
co[cnt]=a[i];
}
}
// cout<<"cnt: "<<cnt<<'\n';
if(n-cnt>k) {
cout<<"-1";
return 0;
} else {
for(ll i=1; i<=cnt; i++) {//只留下每个连续区间最大的,其他的不管
aa[i].vol=m[i];
aa[i].to=i;
aaa[i]=co[i];
answer+=m[i];
// cout<<"sdf "<<co[i]<<" "<<m[i]<<'\n';
}
sort(aa+1, aa+cnt+1, cmp);//按权重排序
// for(ll i=1; i<=cnt; i++) cout<<aa[i].vol<<" "<<aa[i].to<<'\n';
// cout<<"sdfsdfsd "<<asdf<<" "<<k-(n-cnt)<<'\n';
for(ll i=1; i<=cnt; i++) {
// cout<<"i: "<<i<<" "<<aa[i].to-1<<" "<<aa[i].to+1<<" "<<aaa[aa[i].to-1]<<" "<<aaa[aa[i].to+1]<<'\n';
if(asdf==k-(n-cnt)) break;//删除到上限
if(aaa[aa[i].to-1]!=aaa[aa[i].to+1]) answer-=aa[i].vol, asdf++;//在删除后不会出现连续颜色区间的情况下删除权重尽可能小的球
}
// cout<<"sdfsdfsd s "<<asdf<<" "<<k-(n-cnt)<<'\n';
if(asdf!=k-(n-cnt)) cout<<"-1";//如果删不到上限,就-1
else cout<<answer;//输出答案
}
return 0;
}