牛客小白月赛52

本文介绍了五个编程问题的解题思路,包括模拟算法、字符串处理技巧、动态规划的应用,以及如何使用二分法解决环上食虫和分组求对数和问题。

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

牛客小白月赛52

A 签到时刻

思路:
按题意模拟一遍就可以,注意边界即可

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void solve(){
    int n;
    cin>>n;
    int res=0,ans=0;
    for(int i=0;i<n;i++){
        int a,b;
        scanf("%d:%d",&a,&b);
        if(a>7){
            if(a>8){
                ans++;
                continue;
            }
            if(b<=5&&b>0)res++;
            else if(b>5) ans++;
        }
    }
    cout<<res<<" "<<ans<<endl;
}
int main(){
    int t;
    cin>>t;
    while(t--)solve();
}

B 牛牛的身高

思路:
我的想法直接存字符串,然后将高位先补0,从右往左遍历,找到大于5即将当前值和后面的变为0,然后标记有后面进位的1,最后判断最高位是0就不输出最高位,否则就输出最高位

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
void solve(){
    string s;cin>>s;
    s="0"+s;
    int n=s.size();
    int now=0;
    per(i,0,n-1){
        if(s[i]+now>='5'){
            //cout<<i<<endl;
            now=1;
            rep(j,i,n-1)s[j]='0';
        }
        else{
            s[i]=s[i]+now;
            now=0;
        }
    }
    rep(i,0,n-1){
        if(i==0){
            if(s[i]>'0')cout<<s[i];
        }
        else cout<<s[i];
    }
    cout<<endl;
}
signed main(){
    int t;cin>>t;
    while(t--)solve();
}

C 说谎的机器

思路:
首先我们要理解题意,当所选点不在他给的区间就说明他说谎了,所以我们很容易想到差分,找到重叠区间最小值,然后就是找出现几次和指令条数

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e6+7;
int a[N],s[N];
struct node{
    int l,r;
}tr[N];
void cf(int x,int y){
    a[x]+=1;
    a[y+1]-=1;
}
int main(){
    int n,m;
    cin>>n>>m;
    int l=0;
    while(m--){
        int op;
        cin>>op;
        if(op==1){
            int x,y;
            cin>>x>>y;
            cf(x,y);
            tr[l]={x,y};
            l++;
        }
        else if(op==2){
            int x;
            cin>>x;
            cf(x,n);
            tr[l]={x,n};
            l++;
        }
        else{
           int x;
            cin>>x;
            cf(1,x);
            tr[l]={1,x};
            l++;
        }
    }
    for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
    int minx=2e9+7;
    for(int i=1;i<=n;i++){
        //cout<<s[i]<<" ";
        minx=min(minx,s[i]);
    }
    int num=0,x;
    for(int i=1;i<=n;i++){
        if(s[i]==minx){
            num++;
            x=i;
        }
        
    }
    int s=0;
    for(int i=0;i<l;i++){
        if(tr[i].r<x||tr[i].l>x)s++;
    }
    cout<<s<<" "<<num;
}

D 环上食虫

我的思路:二分答案
处理环我们可以直接将数组存两遍,这里-1只会存在所以吃完都不能饱,然后就是二分答案,循环找是否有满足能吃饱的条件下的最大值最小的数

#include<iostream>
#include<algorithm>
 
using namespace std;
#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
const int N = 1e6 + 100;
int a[N];
int b[N];
 
//二分答案
int n,s;
bool check(int x){
    int sum = 0;
    for(int i = 1; i <= 2*n; i++){
        if(b[i] <= x){
            sum += a[i];
            if(sum >= s)
                return true;
        }else
            sum = 0;
    }
    return false;
}
 
signed main(){
    int sum = 0;
    cin>>n>>s;
    for(int i = 1; i <= n; i++){
        int t;cin>>t;
        a[i] = a[i + n] = t;
        sum += a[i];
    }
    for(int i = 1; i <= n; i++){
        int t;cin>>t;
        b[i] = b[i + n] = t;
    }
    if(sum < s){
        puts("-1");
        return 0;
    }
    int l = 1,r = 1e9;
    while(l < r){
        int mid = (l + r) >> 1;
        if(check(mid)){
            r = mid;
        }else{
            l = mid + 1;
        }
    }
    cout<<l;
    return 0;
}

思路2:双指针+区间最大值+环形结构处理
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
const int N = 1e6 + 100;
int a[N];
int b[N];
multiset<int>st;
signed main(){
    int n,s;cin>>n>>s;
    rep(i,1,n){
        cin>>a[i];
        a[i+n]=a[i];
    }
    rep(i,1,n){
        cin>>b[i];
        b[i+n]=b[i];
    }
    int sum=0,r=0;
    int f=0,mn=2e9;
    rep(i,1,n){
        while(r<2*n&&sum<s){
            r++;sum+=a[r];st.insert(-b[r]);
        }
        if(sum>=s&&r-i+1<=n){
            f=1;
            mn=min(mn,-(*st.begin()));
        }
        sum-=a[i];st.erase(st.find(-b[i]));
    }
    if(f)cout<<mn<<endl;
    else cout<<-1<<endl;
}

E 分组求对数和

思路:二分
我们可以将所以数存在vector < int >sum里面排个序用二分找所以可能sum,然后再用vector < int >all[N]记录当前每一组的,然后再将每一组进行排序二分找可能再每一组的答案

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N=1e6+10;
const ll INF=2000000000;
const int mod=998244353;
int n,k;
vector<int> all[N],sum;
int cal(vector<int>&s){
    sort(s.begin(),s.end());
    int ans=0;
    for(int i=0;i<s.size();i++){
       int res=lower_bound(s.begin()+i+1,s.end(),k-s[i])-s.begin();
       res=s.size()-res+1;
       ans+=res;
       ans%=mod;
    }
    return ans;
}
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        int s;
        cin>>s;
        for(int j=1;j<=s;j++){
            int x;
            cin>>x;
            all[i].push_back(x);
            sum.push_back(x);
        }
    }
    int ans=0;
    ans=cal(sum);
    for(int i=1;i<=n;i++){
        ans=(ans-cal(all[i])+mod)%mod;
    }
    cout<<ans;
    return 0;
}


F 骑士战胜魔王

思路:动态规划(Q_Q)不会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linkk_bug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值