专栏文章
题解:CF2145C Monocarp's String
CF2145C题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minlrv9k
- 此快照首次捕获于
- 2025/12/02 04:29 3 个月前
- 此快照最后确认于
- 2025/12/02 04:29 3 个月前
考虑赋权,把所有的
a 设成 ,把所有的 b 设成 ,题意就转化成需要删除一段区间 ,使得 的前缀和与 的后缀和之和为 。考虑把每一个点的后缀和算出来,然后开 个桶, 表示后缀和为 的所有下标。这个可以
vector 或者 set 之类的维护。然后从前往后枚举 ,顺便计算前缀和 ,然后再对应的桶 查询大于等于 的最小值就是确定这个左端点的最优的 。
然后把所有的 ,算出最优的 ,计算 (注意这个时候 和 是不能删除的)的最小值就是答案。
通过代码
CPP#include<bits/stdc++.h>
#define ll long long
using namespace std;
constexpr ll maxn=2e5+5;
ll T,n,arr[maxn];
char ch[maxn];
set<ll> id[maxn<<2];
void solve(){
cin>>n>>(ch+1);
for(int i=1;i<=n;i++){
if(ch[i]=='a')arr[i]=1;
if(ch[i]=='b')arr[i]=-1;
}
for(int i=-n;i<=n;i++){
id[i+maxn].clear();
}
ll suf=0,ans=n,pre=0;
id[0+maxn].insert(n+1);
for(int i=n;i>=1;i--){
suf+=arr[i];
id[suf+maxn].insert(i);
}
if(suf==0){
cout<<0<<"\n";
return;
}
for(int i=0;i<=n;i++){
pre+=arr[i];
auto nxt=id[-pre+maxn].upper_bound(i);
if(nxt==id[-pre+maxn].end())continue;
ll pp=*nxt;
ans=min(ans,pp-i-1);
}
if(ans==n){
cout<<-1<<"\n";
return;
}
cout<<ans<<"\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--){
solve();
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...