题解:P11859 [CCC 2025 Senior] 画画 / Pretty Pens
思路
不难发现如果要更改颜色,应该用每种颜色的次大值的最大值替换最大值最小的那种颜色(用最大值替换后选择次大值与之是等价的)。
明白这一点后就很简单了,我们可以用 multiset 维护每种颜色的最大值,以及最大值和次大值集合,查询时简单判断即可(注释在代码里)。
Code
#include<bits/stdc++.h>
#define int long long
#define SET multiset<int>::iterator
using namespace std;
const int N=2e5+10;
int n,m,q,totmx;
//totmx是最大值之和
int c[N],p[N];
multiset<int> st[N];
multiset<int> secmx,mx;
void delsec(int x){
//在次大值集合中删除某颜色集合的次大值
if(st[x].size()>1){
SET T=st[x].end();
T--;T--;
secmx.erase(secmx.lower_bound(*T));
}
}
void delmx(int x){
//在最大值集合中删除某颜色集合的最大值
if(st[x].size()>=1){
SET T=st[x].end();
T--;
totmx-=(*T);
mx.erase(mx.lower_bound(*T));
}
}
void addsec(int x){
//在次大值集合中加入某颜色集合的次大值
if(st[x].size()>1){
SET T=st[x].end();
T--;T--;
secmx.insert(*T);
}
}
void addmx(int x){
//在最大值集合中加入某颜色集合的最大值
if(st[x].size()>=1){
SET T=st[x].end();
T--;
totmx+=(*T);
mx.insert(*T);
}
}
void out(){
int ans=totmx;
int ssmx=0;
if(secmx.size()>=1){
SET T=secmx.end();
T--;
ssmx=*T;
//ssmx是次大值的最大值
}
ans=max(ans,ans-*mx.begin()+ssmx);//判断更改颜色是否更优
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin>>n>>m>>q;
for(int i=1;i<=n;i++)cin>>c[i]>>p[i],st[c[i]].insert(p[i]);
for(int i=1;i<=m;i++){
addsec(i);addmx(i);
//初始化集合
}
out();
for(int i=1;i<=q;i++){
int op,x,y;
cin>>op>>x>>y;
if(op==1){
delsec(c[x]);delsec(y);delmx(c[x]);delmx(y);
st[c[x]].erase(st[c[x]].lower_bound(p[x]));
st[y].insert(p[x]);
addsec(c[x]);addsec(y);addmx(c[x]);addmx(y);
c[x]=y;
//注意在更改前删去更改集合的最大值和次大值,改完后加回来
}
else if(op==2){
delsec(c[x]);delmx(c[x]);
st[c[x]].erase(st[c[x]].lower_bound(p[x]));
st[c[x]].insert(y);
addsec(c[x]);addmx(c[x]);
p[x]=y;
}
out();
}
return 0;
}