Codeforces Round #788 (Div. 2)(A-C)题解

文章包含三个编程问题的解决方案。第一个问题是关于数组操作,目标是通过特定操作使数组成为非降序。第二个问题涉及字符串处理,计算删除特殊字符的次数。第三个问题讨论排列组合,找出给定排列的填充方案数。每个问题都提供了思路和AC代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A. Prof. Slim

题目链接:Problem - A - Codeforces

题意:给出一个数组,每次操作可以选择两个下标i,j,如果a[i]*a[j]<0,那么可以将它们替换成自己的相反数。注意:a[i]!=0。问操作若干次后是否能让数组是不下降序列。

思路:在正数前面的负数一定要交换符号,交换完了以后check一遍即可。

AC code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
int n,a[N],b[N];
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i]=a[i];
    }
    int pos1=-1,pos2=-1,cnt1=0,cnt2=0;
    for(int i=1;i<=n;i++){
        if(a[i]<0){
            cnt2++;
        }else{
            cnt1++;
        }
    }
    if(cnt1==0 || cnt2==0){
        for(int i=1;i<n;i++){
            if(a[i]>a[i+1]){
                cout<<"NO"<<endl;
                return ;
            }
        }
    }
    int cnt=min(cnt1,cnt2);
    for(int i=1;i<=n;i++){
        if(a[i]>0){
            pos1=i;
            break;
        }
    }
    for(int i=n;i>=1;i--){
        if(a[i]<0){
            pos2=i;
            break;
        }
    }
    while(pos1<pos2 && cnt>=0){
        b[pos1]=-b[pos1];
        b[pos2]=-b[pos2];
        cnt--;
        int t1=pos1;
        int t2=pos2;
        for(int i=pos1+1;i<=n;i++){
            if(a[i]>0){
                pos1=i;
                break;
            }
        }
        if(t1==pos1) break;
        for(int i=pos2-1;i>=1;i--){
            if(a[i]<0){
                pos2=i;
                break;
            }
        }
        if(t2==pos2) break;
    }
    // for(int i=1;i<=n;i++) cout<<b[i]<<' ';
    //     cout<<endl;
    for(int i=1;i<n;i++){
        if(b[i]>b[i+1]){
            cout<<"NO"<<endl;
            return;
        }
    }
    cout<<"YES"<<endl;
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

B. Dorms War

题目链接:Problem - B - Codeforces

题意:给出一个字符串以及一些特殊的字母,如果字符串中某个字母的下一个字母是特殊字母,那么该字母将会被删掉,次数+1。如果特殊字母前面没有其他字母了,那就结束了,输出次数。

思路:观察样例就可以发现,两个相邻的特殊字母的最大距离就是答案,除此之外还有一种可能是从字符串第一个字母到第一个特殊字母的距离要与最大距离相比较,因为如果最大距离还要小于第一个字母到第一个特殊字母的距离的话,那么删除了最大距离的次数之后还有剩余字母可以继续删除。

AC code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,k,vis[30];
string s;
void solve(){
    cin>>n>>s;
    s='!'+s;
    cin>>k;
    for(int i=0;i<=26;i++) vis[i]=0;
    for(int i=1;i<=k;i++){
        char c;
        cin>>c;
        vis[c-'a']=1;
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(vis[s[i]-'a']){
            cnt++;
        }
    }
    if(cnt==1){
        int t=0;
        for(int i=1;i<=n;i++){
            if(vis[s[i]-'a']){
                cout<<t<<endl;
                return;
            }else{
                t++;
            }
        }
    }else if(cnt==0){
        cout<<0<<endl;
        return ;
    }
    int t=0;
    bool ok=0;
    int ans=0;
    for(int i=1;i<=n;i++){
        if(vis[s[i]-'a'] && !ok){
            ok=1;
        }else if(vis[s[i]-'a'] && ok){
            ans=max(ans,t);
            t=0;
            ok=1;
        }else if(vis[s[i]-'a']==0 && ok){
            t++;
        }
    }
    cnt=0;
    for(int i=1;i<=n;i++){
        if(vis[s[i]-'a']){
            break;
        }else{
            cnt++;
        }
    }
    if(cnt>ans){
        cout<<cnt<<endl;
    }else{
        cout<<ans+1<<endl;
    }
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

C. Where is the Pizza?

题目链接:Problem - C - Codeforces

题意:给出排列a和排列b和不完整的排列c,排列c只给了一部分数,对于没给的数,可以选择c[i]=b[i] or c[i]=a[i],问有多少种方案,对1e9取模。

思路:首先假设c【i】全部都是未知数,全部的数都需要从a或者b中获取,假设第一个数选了b[i],那么a[j]=b[i]的下标j也只能再选b[j],即确定选了一个数,那么后面要选的数也就都确定了。如果能够构成一个环,那么对答案的贡献就是乘积因子2,具体看代码模拟一下就懂了。

AC code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
const int mod=1e9+7;
int n,a[N],b[N],c[N],vis[N],mp[N];
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        mp[a[i]]=i;
        vis[i]=0;
    }
    for(int i=1;i<=n;i++) cin>>b[i];
    for(int i=1;i<=n;i++) cin>>c[i];
    int ans=1;
    for(int i=1;i<=n;i++){
        if(vis[a[i]]) continue;
        int j=i;
        bool ok=1;
        if(c[i]) ok=0;
        vis[a[i]]=1;
        while(1){
            j=mp[b[j]];
            if(c[j]) ok=0;
            vis[a[j]]=1;
            if(a[i]==b[j]) break;
        }
        if(ok && (i!=j)) ans=2*ans%mod;
    }
    cout<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值