[ABC314D] LOWER 题解
题意:
给定一个长度为 \(n\) 的字符串,有 \(m\) 次操作,每次操作给定两个整数 \(t\) 和 \(x\),以及一个字符 \(c\),满足以下操作:
\(\hspace{1em}\bullet\) 若 \(t\) 为 \(1\),则将字符串中的第 \(x\) 个字符更改为 \(c\)
\(\hspace{1em}\bullet\) 若 \(t\) 为 \(2\),则将字符串中的所有大写字母变为小写字母
\(\hspace{1em}\bullet\) 若 \(t\) 为 \(3\),则将字符串中的所有小写字母变为大写字母
求最后的字符串
思路:
针对操作 \(1\),直接更改即可,但是由于这个操作可能会改变原有字符串的性质(全部是大写\全部是小写),所以可以维护一个 \(map\),用来判断的是:在上一次使用操作 \(2、3\) 后,字符串中的哪些位置又因为操作 \(1\) 而更改。
针对操作 \(2、3\),因为这两个操作之后,整个字符串要么全为大写,要么全为小写,所以用两个 \(bool\) 的 \(pd\) 和 \(px\) 存储即可。
最后输出的时候,如果 \(pd\) 或 \(px\) 中有一个为一,这意味着最后一个操作不为操作 \(1\),所以直接按大小写输出即可。
否则,意味着最后一步的操作必定为操作 \(1\),字符串在改变大小写后又更改了,所以只需判断 \(map\) 中当前的位置是否更改,更改的话输出原字符串,否则按最后一个操作 \(2、3\) 后的字符串输出。
代码(不喜勿喷)
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
template<typename P>
inline void read(P &x){
P res=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
res=res*10+ch-'0';
ch=getchar();
}
x=res*f;
}
int T=1;
int n;
int Q;
char s[500010];
signed main(){
read(n);
for(int i=1;i<=n;++i) cin>>s[i];
read(Q);
int op,x;
char y;
int sumc=0;
bool qd=0,qx=0;
map<int,bool> q;
for(int i=1;i<=Q;++i){
read(op),read(x);
cin>>y;
if(op==1){
s[x]=y;
q[x]=1;
}
else if(op==2){
qx=1,qd=0;
q.clear();
}
else{
qd=1,qx=0;
q.clear();
};
}
if(qx==1){
for(int i=1;i<=n;++i){
if(q[i]==0){
if(s[i]>='A' && s[i]<='Z') cout<<char(s[i]+32);
else cout<<s[i];
}
else cout<<s[i];
}
cout<<endl;
}
else if(qd==1){
for(int i=1;i<=n;++i){
if(q[i]==0){
if(s[i]>='a' && s[i]<='z') cout<<char(s[i]-32);
else cout<<s[i];
}
else cout<<s[i];
}
cout<<endl;
}
else{
for(int i=1;i<=n;++i){
cout<<s[i];
}
cout<<endl;
}
return 0;
}