牛客练习赛34 A-D

1 篇文章 0 订阅

牛客练习赛34

让我们一起抽卫衣

牛客A题

题意 给你一个脑筋急转弯 规则中文题面:2元买一个酒,2个酒瓶可以换一瓶酒,可以借一瓶酒,但是一定要还

我们发现奇数其实就是 奇数减一的偶数能买的瓶数,1除外,偶数就是能买偶数个

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
char str[150];
int main()
{
    int t;
    scanf("%d",&t);
    getchar();
    while(t--)
    {

        scanf("%s",str);
        int len = strlen(str);
        if(len==1&&str[0]=='1')
            printf("0\n");
        else
        {
            if((str[len-1]-'0')%2==0)
                printf("%s\n",str);
            else
            {

                    str[len-1]--;
                    printf("%s\n",str);
            }
        }
    }
    return 0;
}

牛客B题

题意给你n个数(<=1e5)

问你每次改变一个数的正负号 使所有数的和为0 请问答案有多少个

我们只要暴力模拟一遍 O(n)就行

#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
int arr[100025];
int main()
{
    int n,sum = 0;
    scanf("%d",&n);
    for(int i = 1;i<=n;++i)
    {
        scanf("%d",&arr[i]);
        sum+=arr[i];
    }
    int ans = 0;
    for(int i = 1;i<=n;++i)
    {
        int sum_ = sum;
        if(arr[i]>0)
        {
            sum_ -= arr[i]*2;
        }
        else
        {
            sum_ -= arr[i]*2;
        }
        if(sum_==0) ans++;
    }
    if(ans==0) printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

牛客C题

题意 给你n个点的坐标,m条线段

问你去掉一条线段最少不能覆盖几个线段

其实就是先统计一遍怎么都不会被覆盖的点有几个

然后利用树状数组把每个点被覆盖的次数加起来

如果一个点的覆盖次数是1 代表这个点去掉覆盖就不会被覆盖 开一个前缀和数组

暴力跑一便 复杂度是O(nlogn)

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
const int MAX_N = 100025;
int s[MAX_N<<2],C[MAX_N<<2],ans[MAX_N];
struct node
{
    int l,r;
}arr[MAX_N];
void add(int x,int v)
{
    for(;x<=MAX_N;x+=(x&(-x)))
        C[x]+=v;
}
int getsum(int x)
{
    int res = 0;
    for(;x;x-=(x&(-x)))
        res+=C[x];
    return res;
}
int main()
{
    int n,m,minn = 0x3f3f3f3f,ans_,ans__=0;
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=m;++i)
    {
        scanf("%d%d",&arr[i].l,&arr[i].r);
        add(arr[i].l,1);
        add(arr[i].r+1,-1);
    }
    for(int i = 1;i<=n;++i)
    {
        int tmp = getsum(i);
        if(tmp==0) ans__++;
        //cout << "tmp = " << tmp<< endl;
        if(tmp==1) ans[i] = ans[i-1] + 1;
        else ans[i] = ans[i-1];
    }
    for(int i = 1;i<=m;++i)
    {
        int tmp = ans[arr[i].r] - ans[arr[i].l-1];
        //cout << tmp << endl;
        if(tmp<=minn)
        {
            minn = tmp;
            ans_ = i;
        }
    }
    printf("%d %d\n",ans_,minn+ans__);
    return 0;
}

牛客D题

题意 给你n个纸票 有不同面值 问你能不能组合成1-m所有面值

不难理解1 肯定是要出现的 然后我们可以排个序 sum代表之前纸币能凑成的钱 只要sum+1<=arr[i] (2<=i<=n)

就能保证 当前能凑齐 sum+arr[i] 所有钱数

然后见代码吧

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <time.h>
using namespace std;
int arr[1025];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=n;++i)
    {
    scanf("%d",&arr[i]);
    }
    sort(arr+1,arr+1+n);
    if(arr[1]!=1)
    {
        printf("NO\n");
        return 0;
    }
    long long sum = 1;
    for(int i = 2;i<=n;++i)
    {
        if(arr[i]>sum+1)
        {
            break;
        }
        sum+=arr[i];
    }
    if(sum>=m) printf("YES\n");
    else printf("NO\n");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值