NOI模拟 Mizuki 与进化
1.NOIP模拟 排序2.NFLS 231031 比赛总结3.JOI2013Final/LOJ2763 现代豪宅4.省选模拟 序列5.省选模拟 过路费6.NOI模拟 序列7.NOI模拟 大战波特
8.NOI模拟 Mizuki 与进化
9.NOI模拟 刀客球10.NOI模拟 真夏は誰のモノ11.NOI模拟 树数术12.NOI模拟 序列13.NOI模拟 GCD14.NOI模拟 开关15.NOI模拟 排序幻觉16.NOI模拟 UTF-817.NOI模拟 捉迷藏18.退背包简介/NOI模拟 卖画19.CSP模拟 取模20.CSP模拟 矩阵操作21.AGC007F Shik and Copying String22.洛谷P10336 [UESTCPC 2024] 2-聚类算法23.NFLS 241014 比赛总结24.QOJ5173 染色25.洛谷P11183 [ROIR 2018 Day2] 大数据处理涉及知识点:贪心
题意
给你一个只包含 A B C
的长度为 的字符串,问能否将该字符串划分为 个子序列,子序列只能是 AB AC BC
中的一个,或输出无解。
思路
设 A B C
的个数分别为 ,为 AB AC BC
的子序列个数分别为 ,那么有如下等式:
经过简单演算可以得到:
此时如果算出来 不是一个正整数说明无解。
接下来我们让前 个 B
去匹配它右边离它最近的 C
;然后让剩下 个 B
去匹配它左边离它最近的 A
;最后再让剩下的 A
和 C
两两匹配即可。匹配过程中如果匹配失败说明无解。
贪心正确性:
为什么
B
匹配右边离它最近的C
?很明显,如果匹配更远的
C
,有可能会抢了它左边的B
本来可以匹配到的C
。匹配B
的情况同理。为什么前面的
B
去匹配C
,后面的B
去匹配A
?匹配
C
的肯定是越前面越好,匹配A
的肯定是越后面越好,这样匹配才会使得最后A
与C
的匹配更容易成功,可以假设交换发现一定不优。
代码
#include<bits/stdc++.h>
#define getmid int mid=(l+r)/2
using namespace std;
template<class T>inline void wt(T x,char endch='\0'){
static char wtbuff[20];
static int wtptr;
if(x==0){
putchar('0');
}
else{
if(x<0){x=-x;putchar('-');}
wtptr=0;
while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
while(wtptr--) putchar(wtbuff[wtptr]);
}
if(endch!='\0') putchar(endch);
}
const int MAXN=2e5+5;
int n,bel[MAXN],cnt[3],cntab,cntbc;
bool vis[MAXN];
string s;
queue<int>q;
bool check_remain(){
for(int i=1;i<=n;i++){
if(s[i]=='B' && vis[i]==0) return false;
}
for(int i=1;i<=n;i++){
if(vis[i]) continue;
if(s[i]=='A') q.push(i);
else if(q.empty()) return false;
else bel[i]=q.front(),q.pop();
}
if(!q.empty()) return false;
return true;
}
int main(){
// freopen("evolution.in","r",stdin);
// freopen("evolution.out","w",stdout);
cin>>n>>s;n<<=1;
if(s.front()=='C' || s.back()=='A'){puts("No");return 0;}
s=" "+s;
for(int i=1;i<=n;i++) cnt[s[i]-'A']++;
if(cnt[0]+cnt[1]+cnt[2]==0){puts("No");return 0;}
if((cnt[0]+cnt[1]-cnt[2]<0) || (cnt[0]+cnt[1]-cnt[2])&1){puts("No");return 0;}
if((cnt[0]-cnt[1]+cnt[2]<0) || (cnt[0]-cnt[1]+cnt[2])&1){puts("No");return 0;}
if((-cnt[0]+cnt[1]+cnt[2]<0) || (-cnt[0]+cnt[1]+cnt[2])&1){puts("No");return 0;}
cntab=(cnt[0]+cnt[1]-cnt[2])/2;
cntbc=(-cnt[0]+cnt[1]+cnt[2])/2;
// cout<<cnt[0]<<' '<<cnt[1]<<' '<<cnt[2]<<' '<<cntab<<' '<<cntbc<<endl;
int ptr,i;
s[n+1]='C';
for(i=1;i<=n && cntbc>0;i++){
if(s[i]!='B') continue;
vis[i]=1;
ptr=i+1;
while(vis[ptr] || s[ptr]!='C') ptr++;
if(ptr>n){puts("No");return 0;}
vis[ptr]=1;bel[ptr]=i;
cntbc--;
}
int tmp=i;
s[0]='A';
for(i=n;i>=tmp && cntab>0;i--){
if(s[i]!='B') continue;
vis[i]=1;
ptr=i-1;
while(vis[ptr] || s[ptr]!='A') ptr--;
if(ptr<0){puts("No");return 0;}
vis[ptr]=1;bel[i]=ptr;
cntab--;
}
if(!check_remain()) puts("No");
else{
puts("Yes");
for(i=1;i<=n;i++){
if(bel[i]) wt(bel[i],' '),wt(i,'\n');
}
}
return 0;
}
本文作者:MessageBoxA
本文链接:https://www.cnblogs.com/SkyNet-PKN/p/18183281
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步