牛客小bai月赛52题解

题目地址:牛客小白月赛52

A:略

B:牛牛的身高

从右向左遍历每一位就行

#include<iostream>
#include<cstring>

using namespace std;

char a[10];

int main(){
    int t;
    while(cin>>t){
        while(t--){
            a[0] = '0';
            scanf("%s",a+1);
            int len = strlen(a+1);
            if(len == 1 && a[1] - '0' < 5){
                    cout<<a[1]<<endl;;
            }else{
                int idx = 100;
                for(int i = len; i >= 1; i--){
                    int temp = a[i] - '0';
                    if(temp>=5){
                        a[i-1] = a[i-1] +1;
                        idx = i-1;

                    }

                }
                if(a[0] != '0')
                    cout<<a[0];
                for(int i = 1; i <= len; i++){
                    if(i <= idx)
                        cout<<a[i];
                    else
                        cout<<0;

                }
                cout<<endl;
            }
        }
    }

    return 0;
}

C:说谎的机器

 区间覆盖问题,将2,3,操作转化为1,如果直接每次都循环修改区间的值会超时,这里使用差分数组统计每个区间覆盖的次数,找到最小的就是答案

#include<iostream>
#include<cstring>
#include<climits>

using namespace std;

int b[1000100];

int main(){
    int n,m;
    while(cin>>n>>m){
        memset(b,0,sizeof(b));
        int op;
        int ans,mi;
        int o = m;
        while(m--){
            cin>>op;
            if(op == 1){
                int x,y;
                cin>>x>>y;
                b[x]++;
                b[y+1]--;
            }
            if(op == 2){
                int x;
                cin>>x;
                b[x]++;
            }if(op == 3){
                int x;
                cin>>x;
                b[1]++;
                b[x+1]--;
            }
        }
        mi = INT_MAX;
        for(int i = 1; i <= n; i++){

            b[i] = b[i] + b[i-1];
            //cout<<b[i]<<endl;
            mi = min(mi,b[i]);
        }
        ans = 0;
        for(int i = 1; i <= n; i++){
            if(b[i] == mi)
                ans ++;
        }
        cout<<o-mi<<" "<<ans<<endl;
    }

    return 0;
}

D:环上食虫

 二分答案的最大值最小化模板题,直接二分所有奶油含量然后check一下是否满足饱腹值修改对应区间就行,这题建议直接开搞,

#include<iostream>
#include<algorithm>

using namespace std;

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;
}

int main(){
    long long 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;
        }
    }
    printf("%d\n",l);
    return 0;
}

E:分组求对数和

 两个队列,each表示每个小朋友的数字,sum表示所有小朋友的数字,分别从小到大排序,然后枚举每一个值v 去找所有y>=k-v的情况,然后减去同一个人的组合就行

#include<iostream>
#include<vector>
#include<algorithm>
#define mod 998244353

using namespace std;

vector<int> each[1000010];
vector<int> sum;

int n,k;
int main(){
    scanf("%d %d",&n,&k);
    int m;
    int a;
    for(int i = 0; i < n; i++){
        scanf("%d",&m);
        for(int j = 0; j < m; j++){
            scanf("%d",&a);
            each[i].push_back(a);
            sum.push_back(a);
        }
        sort(each[i].begin(),each[i].end());
    }
    sort(sum.begin(),sum.end());
    long long ans = 0;
    for(int i = 0; i < n; i++){
        m = each[i].size();
        for(int j = 0; j < m; j++){
            int v = each[i][j];
            int y = k - v;
            ans += (sum.end() - upper_bound(sum.begin(),sum.end(), y - 1))-
                   (each[i].end() - upper_bound(each[i].begin(),each[i].end(),y-1));
        }
    }
    ans /= 2;
    cout<<ans%mod<<endl;
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值