cf2111e
CF2111E Changing the String
题意
给定仅由 \(abc\) 构成的字符串,\(q\) 次操作可以将串中任意一个 \(x\) 修改为 \(y\),可以选任意操作不做,使得字符串字典序最小。\(\sum n,q \leq 2\times 10^5,s_i,x,y\in \{a,b,c\}\)。
题解
字典序最小显然是从前往后贪心。由于字符集很小,直接分类讨论。
- \(s_i=a\),啥都不需要干。
- \(s_i=b\),考虑 \(b\rightarrow a\),如果有这种操作就执行。还有可能是 \(b\rightarrow c\rightarrow a\),先看 \(b\rightarrow c\),在 \(c\rightarrow a\) 中选第一个比 \(b\rightarrow c\) 大的。
- \(s_i=c\),考虑 \(c\rightarrow b\) 或 \(a\),这种直接做。还有 \(c\rightarrow b\rightarrow a\),和上一种一样。
各种操作可以set维护。复杂度 \(O((n+q)\log q)\)。aclink。
坑
- 代码好写。
代码
#include<bits/stdc++.h>
#define i64 long long
#define L(a,b,c,d) for(int a=b;a<=c;a+=d)
#define R(a,b,c,d) for(int a=b;a>=c;a-=d)
using namespace std;
const int N=2e5+5;
void solve();
int n,q;
set<int> ba,bc,ca,cb;
char s[N];
signed main(){
int Test=1;
scanf("%d",&Test);
while(Test--) solve();
return 0;
}
void solve(){
scanf("%d%d",&n,&q);
scanf("%s",s+1);
ba.clear(),bc.clear(),ca.clear(),cb.clear();
L(i,1,q,1){
char p[2],q[2];
scanf("%s%s",p,q);
if(p[0]=='b'){
if(q[0]=='a') ba.insert(i);
else if(q[0]=='c') bc.insert(i);
}
else if(p[0]=='c'){
if(q[0]=='a') ca.insert(i);
else if(q[0]=='b') cb.insert(i);
}
}
L(i,1,n,1){
if(s[i]=='b'){
if(!ba.empty()){
s[i]='a';
ba.erase(ba.begin());
}
else if(!bc.empty()){
auto it=ca.upper_bound(*bc.begin());
if(it!=ca.end()){
bc.erase(bc.begin());
ca.erase(it);
s[i]='a';
}
}
}
else if(s[i]=='c'){
if(!ca.empty()){
s[i]='a';
ca.erase(ca.begin());
}
else if(!cb.empty()){
auto it=ba.upper_bound(*cb.begin());
if(it!=ba.end()){
cb.erase(cb.begin());
ba.erase(it);
s[i]='a';
}
else{
s[i]='b';
cb.erase(cb.begin());
}
}
}
}
printf("%s\n",s+1);
}
本文来自博客园,作者:jess1ca1o0g3,转载请注明原文链接:https://www.cnblogs.com/jess1ca1o0g3/p/19061315

浙公网安备 33010602011771号