Codeforces Round 938 (Div. 3) (A-E)

文章包含四个编程竞赛题目,涉及模拟、数组操作、动态规划和差分算法。展示了如何使用C++解决关于酸奶销售、逐格填充、深海居民和不准确序列搜索的问题,以及一个使用差分优化暴力方法的长逆序对问题。

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

A.Yogurt Sale

代码

签到题

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef long long ll;
#define pll pair<ll,ll>
#define endl "\n"
const int Inf =1e18;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

inline ll read();

void solve() {
    int n=read(),a=read(),b=read();
    int ans1=a*n;
    int ans2=(n/2)*b+(n%2)*a;
    cout<<min(ans1,ans2)<<endl;

}

signed main() {
//    ios::sync_with_stdio(false);
//    cin.tie(nullptr),cout.tie(nullptr);
    int tt = 1;
    tt=read();
    while (tt--)
        solve();
}

inline ll read() {
    ll x = 0, ch = getchar(), f = 1;
    while (!isdigit(ch)) {
        if (ch == '-')
            f = -f;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

B.Progressive Square

思路

从左上角开始模拟即可

代码

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef long long ll;
#define pll pair<ll,ll>
#define endl "\n"
const int Inf =1e18;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;

inline ll read();
int c[N];
vector<int>ans(N);
void solve() {
    int n=read(),a=read(),b=read();
    map<int,int>mp;
    ans.clear();
    for(int i=1;i<=n*n;i++){
        c[i]=read();
        mp[c[i]]++;
    }
    sort(c+1,c+1+n*n);
    bool f=0;
    ans[1]=c[1];
    for(int i=2;i<=n*n;i++){
        if(i>n){
            if(mp[ans[i-n]+a]>=1)
                mp[ans[i-n]+a]--,ans[i]=ans[i-n]+a;
            else{
                f=1;
                break;
            }
        }else{
            if(mp[ans[i-1]+b]>=1)
                mp[ans[i-1]+b]--,ans[i]=ans[i-1]+b;
            else{
                f=1;
                break;
            }
        }
    }
    if(f==1)cout<<"NO"<<endl;
    else cout<<"YES"<<endl;

}

signed main() {
//    ios::sync_with_stdio(false);
//    cin.tie(nullptr),cout.tie(nullptr);
    int tt = 1;
    tt=read();
    while (tt--)
        solve();
}

inline ll read() {
    ll x = 0, ch = getchar(), f = 1;
    while (!isdigit(ch)) {
        if (ch == '-')
            f = -f;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

C.Inhabitant of the Deep Sea(模拟)

思路

将船分为左右两边,左边(k+1)/2,右边k/2,模拟是否会被摧毁即可

代码 

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef long long ll;
#define pll pair<ll,ll>
#define endl "\n"
const int Inf =1e18;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

inline ll read();
int a[N];
void solve() {
    int n=read(),k=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    int sum1=(k+1)/2;
    int sum2=k/2;
    int l=1,r=n;
    int ans=0;
    bool f1=0,f2=0;
    while(l<r){
        if(a[l]<=sum1)ans++,sum1-=a[l++];
        else f1=1;
        if(a[r]<=sum2)ans++,sum2-=a[r--];
        else f2=1;
        if(f1==1&&f2==1)break;
    }
    if(l==r&&a[l]<=sum1+sum2)ans++;
    cout<<ans<<endl;

}

signed main() {
//    ios::sync_with_stdio(false);
//    cin.tie(nullptr),cout.tie(nullptr);
    int tt = 1;
    tt=read();
    while (tt--)
        solve();
}

inline ll read() {
    ll x = 0, ch = getchar(), f = 1;
    while (!isdigit(ch)) {
        if (ch == '-')
            f = -f;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

D. Inaccurate Subsequence Search(双指针)

思路

使用map映射来存储当前区间各个值的数量,用一个参数num来存储符合条件的数字数量,双指针跑一遍即可

代码

注意在左右指针移动时更新映射中的值

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef long long ll;
#define pll pair<ll,ll>
#define endl "\n"
const int Inf =1e18;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

inline ll read();
int a[N],b[N];

void solve() {
    int n=read(),m=read(),k=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    map<int,int>mp;
    for(int i=1;i<=m;i++){
        b[i]=read();
        mp[b[i]]++;
    }
    int l=1,r=m;
    map<int,int>mpp;
    int num=0,sum=0;
    for(int i=l;i<=r;i++){
        mpp[a[i]]++;
        if(mp[a[i]]>=mpp[a[i]])num++;
    }
    if(num>=k)sum++;
    if(mpp[a[l]]-1<mp[a[l]])num--;
    mpp[a[l++]]--;
    mpp[a[++r]]++;
    while(r<=n){
        if(mp[a[r]]>=mpp[a[r]])num++;
        if(num>=k)sum++;
        if(mpp[a[l]]-1<mp[a[l]])num--;
        mpp[a[l++]]--;
        mpp[a[++r]]++;
    }
    cout<<sum<<endl;


}

signed main() {
//    ios::sync_with_stdio(false);
//    cin.tie(nullptr),cout.tie(nullptr);
    int tt = 1;
    tt=read();
    while (tt--)
        solve();
}

inline ll read() {
    ll x = 0, ch = getchar(), f = 1;
    while (!isdigit(ch)) {
        if (ch == '-')
            f = -f;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

E.Long Inversions(差分+暴力)(或树状数组)

思路

首先,题目中n<=5000,很明显可以使用n方的时间复杂度来暴力解决问题。从n到1遍历答案的长度,在每次循环中从前往后遍历,如果当前位数为0,则将本位后的k位都反转。但如果每次都遍历进行暴力反转,那么时间复杂度将来到O(n^3)。所以还是需要来进行一些操作来优化。

 这里采用差分的操作,使用参数now来存储当前翻转的次数,在i+k的位置进行标记,到达i+k时将反转次数减去。

代码

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef long long ll;
#define pll pair<ll,ll>
#define endl "\n"
const int Inf =1e18;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

inline ll read();

int a[N];


void solve() {
    int n=read();
    string s;
    cin>>s;
    for(int k=n;k>=1;k--){
        string ss=s;
        for(int i=0;i<n+n;i++){
            a[i]=0;
        }
        int now=0;
        for(int i=0;i<n;i++){
            now-=a[i];
            if(now%2==1){
                if(ss[i]=='1') ss[i]='0';
                else ss[i]='1';
            }
            if(ss[i]=='0'&&i<=n-k){
                now++;
                a[i+k]++;
                ss[i]='1';
            }
        }
        bool f=0;
        for(int i=0;i<n;i++){
            if(ss[i]=='0'){
                f=1;
                break;
            }
        }
        if(f==0){
            cout<<k<<endl;
            return ;
        }

    }


}

signed main() {
//    ios::sync_with_stdio(false);
//    cin.tie(nullptr),cout.tie(nullptr);
    int tt = 1;
    tt=read();
    while (tt--)
        solve();
}

inline ll read() {
    ll x = 0, ch = getchar(), f = 1;
    while (!isdigit(ch)) {
        if (ch == '-')
            f = -f;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值