CF每日5题Day2(1400)
根据通过人数二分法练题,每日打卡。
1- 1427B
- 一组字符串 n n n个W x x x组连续W 得分 2 n − x 2n-x 2n−x
- 得分尽量高 就要增大 n n n 减小 x x x
- 所以要把W尽量连起来
老是wa2 202行错误 想不出来哪里没想到 决定先放一放
struct idx{
int l,r;
};
void solve(){//1427B
int n,k;cin>>n>>k;
string s;cin>>s;
vector<idx>va;
int w=0,wcnt=0,i=0,l=0;
int fg=0;//去除开头的L 因为开头放W没有在后面放加的多
while(i<n){
if(s[i]=='W'){
wcnt++;
while(i<n&&s[i]=='W'){
w++;
i++;
}
fg=1;
}
if(!fg){i++;continue;}
if(s[i]=='L'){
l=i;
while(i<n&&s[i]=='L')i++;
if(i-l>0)va.push_back({l,i});
}
}
// for(auto x:va){
// cout<<x.l<<' '<<x.r<<endl;
// }
if(w+k>=n)return cout<<2*n-1<<endl,void();
sort(va.begin(),va.end(),[&](idx x,idx y){
return (x.r-x.l)<(y.r-y.l);
});
for(auto x:va){
if(k<=0)break;
int cg=x.r-x.l;
if(x.r<n&&k>=cg)wcnt=max(wcnt-1,0ll);
w+=min(k,cg);
k-=cg;
}
if(k>0){
if(w==0)wcnt++;
w+=k;
}
cout<<2*w-wcnt<<endl;
}
2- 797B
水题
- 都是正的相加 和一定是子序列中最大的
- 如果这个最大的和是奇数 直接输出
- 不是奇数 看去除某个正数/加上某个负数 能不能成奇数 并找最大的和
void solve(){
int n;
cin>>n;
vector<int>a(n+1);
int sum=0;
forr(i,1,n){
cin>>a[i];
if(a[i]>0)sum+=a[i];
}
if(sum%2)return cout<<sum<<endl,void();
else{
int ans=-1e4-10;
forr(i,1,n){
int ad=(a[i]>0?-a[i]:a[i]);
if((ad+sum)%2){
ans=max(ad+sum,ans);
}
}
cout<<ans<<endl;
}
}
3- 1103A
题很短 但愣是没看懂
意思是放长方形 0是竖的 1是横的
放满一行或一列就可以消除 然后空出来继续放
构造水题
- 尽量消除
- 竖的横的分着放 不会重叠
void solve(){
string s;cin>>s;
int r=0,c=0;
for(auto i:s){
if(i=='0'){
cout<<"1 "<<(r+1)<<endl;
r=(r+1)%4;
}else {
cout<<"4 "<<c+1<<endl;
c=(c+2)%4;
}
}
}
4- 2045C 字符串处理
- ”有趣缩写“要求有来自s、t的非空子串两种组合,就说明要有一个字母c,s和t都有,这样要么是s提供c,要么是t提供c。
- 注意这个字母不能是s的开头或t的结尾,如果是的话不能保证 不提供c的 字符串 非空,那就只有一种组合,不有趣。
- 思路就是先找以每个字母结尾的s前缀、t后缀,再遍历每个字母,找能连接起的最短字符串。
一开始因为判定的时候,无穷大N选小了,一直wa16…蠢炸了
const int N=4e5+10;
void solve(){
string s,t;
vector<int>ss(27,N),tt(27,N);
cin>>s>>t;
int sl=s.size(),tl=t.size();
forr(i,1,sl-1){
if(ss[s[i]-'a']==N)ss[s[i]-'a']=i+1;
}
reforr(i,0,tl-2){
// cout<<t[i]<<' ';
if(tt[t[i]-'a']==N)tt[t[i]-'a']=tl-i;
}
int len=N;
string ans="";
for(int i=0;i<=25;i++){
len=min(ss[i]+tt[i],len);
}
if(len==N)return cout<<-1<<endl,void();
for(int i=0;i<=25;i++){
if(len==ss[i]+tt[i]){
string cp=s.substr(0,ss[i])+t.substr(tl-tt[i]+1);
ans=cp;
}
}
cout<<ans<<endl;
}
5- 297B 差分
水题
- 对称交换 所以只需要考虑一半
- 反转两次 就相当于没反转 不操作
- 反转单数次就要反转
- (别急 有反转
void solve(){
string s;
cin>>s;
int len=s.size();
s=" "+s;
vector<int>cnt(len+2,0);
int m;cin>>m;
forr(i,1,m){
int a;cin>>a;
cnt[a]++;
}
int sum=0;
//对称的 处理一半就行
forr(i,1,len/2){
sum+=cnt[i];
// cout<<sum<<endl;
if(sum%2==1){
char tp=s[i];
s[i]=s[len-i+1];
s[len-i+1]=tp;
// cout<<s<<endl;
}
}
cout<<s<<endl;
}