zoukankan      html  css  js  c++  java
  • 牛客团队赛50&CF#664(Div2)

    牛客团队赛50

    A.Rental Service

    题目:https://ac.nowcoder.com/acm/contest/6306/A

    题解:牛有两种卖法:一个是卖奶,一个是租赁,比较二者哪个获利最多。

    一道典型的贪心问题。

    1.留下产奶量多的奶牛;

    2.卖牛奶先卖给出价高的商铺;

    3.把奶牛租给出价高的邻居。

    我们按产奶量从多到少排序,按商铺价格从高到低排序,按出租的价格从高到低排序。

    这里用到一个前缀和数组,来计算奶牛租赁的。

    我们枚举第一头奶牛卖奶,其余奶牛租赁的最大价格,然后依次枚举,取其最大即可。注意代码中的:ans=max(ans,num+c[min(n-i,r)]);c为前缀和数组表示剩余n-i头奶牛租赁的最大价格

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const ll N=100010;
    ll n,m,r;
    ll a[N],c[N];
    ll ans,sum;
    struct node
    {
        ll q,p;
    }b[N];
    
    bool cmp(node a,node b)
    {
        if(a.p!=b.p)
            return a.p>b.p;
        else
            return a.q>b.q;
    }
    
    bool cmp2(int a,int b)
    {
        return a>b;
    }
    
    int main()
    {
        ll i,j,k;
        ll flag=0;
        cin>>n>>m>>r;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+n+1,cmp2);
        for(i=0;i<m;i++)
            cin>>b[i].q>>b[i].p;
        sort(b,b+m,cmp);
        for(i=1;i<=r;i++)
            cin>>c[i];
        sort(c+1,c+r+1,cmp2);
        for(i=1;i<=r;i++)
            c[i]+=c[i-1];
        ll num=0;
        j=0;
        for(i=1;i<=n;i++)
        {
            while(j<m&&a[i]>=b[j].q)
            {
                a[i]-=b[j].q;
                num+=b[j].p*b[j].q;
                j++;
            }
            if(j<m)
            {
                b[j].q-=a[i];
                num+=a[i]*b[j].p;
            }
            //前缀和数组模拟最大值,看有几个卖奶,几个租赁
            ans=max(ans,num+c[min(n-i,r)]);
        }
        cout<<ans<<endl;
        return 0;
    }

     

    H:Cow Coupons

    题目:https://ac.nowcoder.com/acm/contest/6306/H

    解法:也是一道谈心题,可从两方面入手:优惠券足够,优惠券不够

    ①优惠足够,就看钱数,按优惠后的价格从低到高进行购买

    ②优惠券不够,先按照优惠后的价格从低到高进行购买,买完后标记上,直到优惠券不够了钱还够,或者优惠券够钱不够了。

    优惠券够钱不够,则直接输出;优惠券不够了钱够,就将数组按照原来的价格从低到高排序,便利购买时已标记过的不购买,计算直到钱不够为止。

    代码:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=50010;
    struct node
    {
        ll p,c;
        bool flag;
    }a[N];
    
    bool cmp1(node a,node b)
    {
        if(a.c!=b.c)
            return a.c<b.c;
        else
            return a.p>b.p;
    }
    
    bool cmp2(node a,node b)
    {
        return a.p<b.p;
    }
    
    int main()
    {
        ll i,j,n,k,m;
        ll ans=0;
        cin>>n>>k>>m;
        for(i=0;i<n;i++)
        {
            cin>>a[i].p>>a[i].c;
            a[i].flag=false;
        }
        sort(a,a+n,cmp1);
        if(k>=n)
        {
            for(i=0;i<n;i++)
            {
                if(m>=a[i].c)
                {
                    m-=a[i].c;
                    ans++;
                }
                else
                    break;
            }
            cout<<ans<<endl;
        }
        else
        {
            bool flag=false;
            for(i=0;i<n;i++)
            {
                if(m>=a[i].c&&k>0)
                {
                    m-=a[i].c;
                    a[i].flag=true;
                    k--;
                    ans++;
                }
                if(k==0)
                    break;
                if(m<a[i].c)
                {
                    flag=true;
                    break;
                }
            }
            if(flag==true)
                cout<<ans<<endl;
            else
            {
                sort(a,a+n,cmp2);
                for(i=0;i<n;i++)
                {
                    if(a[i].flag==false)
                    {
                        if(m>=a[i].p)
                        {
                            m-=a[i].p;
                            ans++;
                        }
                        else
                            break;
                    }
                }
                cout<<ans<<endl;
            }
        }
        return 0;
    }

     

    J.Haybale Stacking

    题目:https://ac.nowcoder.com/acm/contest/6306/J

    题解:一道差分题。根据【l,r】,在这个区间每次都加1,因此设计一个差分数组d[N],他表示d[i]=a[i]-a[i-1],因此,每次给一段范围,

    就让d[l]++,d[r+1]--。这样用0(1)的操作解决,之后在遍历a数组,a[i]=a[i-1]+d[i];得到最终的a数组,然后输出数组的中间数a[n/2+1]

    代码:

    #include<cstdio>
    #include<algorithm>
    #define MAXN 1000005
    using namespace std;
    int a[MAXN],d[MAXN];
    int n,p;
    int main(){
        scanf("%d%d",&n,&p);
        while(p--){
            int l,r;
            scanf("%d%d",&l,&r);
            d[l]++,d[r+1]--;
        }
        for(int i=1;i<=n;i++){
            a[i]=a[i-1]+d[i];
        }
        sort(a+1,a+n+1);
        printf("%d
    ",a[n/2+1]);
        return 0;
    }

     

    CF

    A. Boboniu Likes to Color Balls

    题目:https://codeforces.com/contest/1395/problem/A

    题解:要想保证他为回文串,满足要求的是:

    r%2+g%2+b%2+w%2<=1,意思是奇数个为1个情况

    r&&g&&b&&(r%2+g%2+b%2+w%2>=3),奇数个为3个或者4个,并且r,g,b都得大于0,因为需要一次变化才能将其变成回文串,因此至少他们三个得大于0.

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    
    int main()
    {
        ll t,i,j,r,g,b,w;
        cin>>t;
        for(i=0;i<t;i++)
        {
            cin>>r>>g>>b>>w;
            if(r%2+g%2+b%2+w%2<=1||(r&&g&&b&&(r%2+g%2+b%2+w%2>=3)))
                cout<<"Yes"<<endl;
            else
                cout<<"No"<<endl;
        }
        return 0;
    }

     

    B. Boboniu Plays Chess

    题目:https://codeforces.com/contest/1395/problem/B

    题解:从初始位置开始,确定一条唯一的遍历路线即可。

    我的路线是:先从他的位置开始遍历其右边的位置,一直到边缘,然后再开始从他的左边开始遍历到左边缘,然后向上遍历,在向下遍历。很简单的

    代码:

    #include<iostream>
    using namespace std;
    const int N=110;
    int sx,sy;
    
    int main()
    {
        int i,j,n,m,k;
        cin>>n>>m>>sx>>sy;
        for(i=sy;i<=m;i++)
            cout<<sx<<" "<<i<<endl;
        for(i=sy-1;i>=1;i--)
            cout<<sx<<" "<<i<<endl;
        k=sx-1;
        int flag=0;
        while(k>=1)
        {
            if(flag==0)
            {
                for(i=1;i<=m;i++)
                    cout<<k<<" "<<i<<endl;
                flag=1;
                k--;
            }
            else
            {
                for(i=m;i>=1;i--)
                    cout<<k<<" "<<i<<endl;
                flag=0;
                k--;
            }
        }
        k=sx+1;
        while(k<=n)
        {
            if(flag==0)
            {
                for(i=1;i<=m;i++)
                    cout<<k<<" "<<i<<endl;
                flag=1;
                k++;
            }
            else
            {
                for(i=m;i>=1;i--)
                    cout<<k<<" "<<i<<endl;
                flag=0;
                k++;
            }
        }
        return 0;
    }

     

    C. Boboniu and Bit Operations

    题目:https://codeforces.com/contest/1395/problem/C

    题解:一开始想的是用map数组来尽可能的收集相同的比a[i]本身要小的数,结果第三个样例都没过,然后知道这样没依据,行不通

    然后看K的数据范围试2^9,n和m是200,枚举k,复杂度为O(knm),最大是2*10^8次方,还是可以接受的

    因此枚举k,然后判断整个k能否于a[i]&b[j]进行或运算,并且等于k,如果可以遍历整个a数组,那么k就是最终的答案。

    代码:

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include<iostream>
    using namespace std;
    int n, m, a[205], b[205];
    int main() {
        int i,j,k;
        cin>>n>>m;
        for(i=0;i<n;i++)
            cin>>a[i];
        for(i=0;i<m;i++)
            cin>>b[i];
        for(k=0;k<=(1<<9);k++)
        {
            bool f=false;
            for(i=0;i<n;i++)
            {
                bool flag=false;
                for(j=0;j<m;j++)
                {
                    if((k|(a[i]&b[j]))==k)
                    {
                        flag=true;
                        break;
                    }
                }
                if(flag==false)
                {
                    f=true;
                    break;
                }
            }
            if(f==false)
            {
                cout<<k<<endl;
                break;
            }
        }
        return 0;
    }

     

    D. Boboniu Chats with Du

    题目:https://codeforces.com/contest/1395/problem/D

    题解:对于这个,我们采取贪心的思想,将大于的分为一组,小于的分为一组,然后按从大到小排序。

    构造前缀和数组,然后我们的思想是,大于的那一组出现一次就要占去d+1个天数,实则不是,可以将其放到最后,那么就会只站一天,因此我们要充分的利用最后一天。

    因此只要枚举从0~len1天,a中可以出现的个数,剩余的就是b中个数,然后取最大。

    务必要注意一点:判断k>n,否则会导致数组下标不在范围内。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    ll n,m,d;
    ll a[N],b[N];
    ll pra[N],prb[N];
    bool cmp(ll a,ll b)
    {
        return a>b;
    }
    ll ans;
    int main()
    {
        ll i,j,x;
        ll len1=0,len2=0;
        cin>>n>>d>>m;
        for(i=1;i<=n;i++)
        {
            cin>>x;
            if(x>m)
                a[++len1]=x;
            else
                b[++len2]=x;
        }
        sort(a+1,a+len1+1,cmp);
        sort(b+1,b+len2+1,cmp);
        for(i=1;i<=len1;i++)
            pra[i]=pra[i-1]+a[i];
        for(i=1;i<=len2;i++)
            prb[i]=prb[i-1]+b[i];
        ans=prb[len2];
        for(i=1;i<=len1;i++)
        {
            int k=(i-1)*(d+1)+1;
            //不判断会导致数组超界
            if(k>n)
                break;
            ll t=min(n-k,len2);
            ans=max(ans,pra[i]+prb[t]);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    使用自己的key对app进行签名
    pl/sql中文乱码解决办法
    Oracle存储过程中创建表的权限
    pl/sql中获得sql语句执行后影响的行数
    申请Android Map APIKey
    vs快捷键
    ODAC安装配置与使用详解
    .net不安装Oracle11g客户端直接使用ODAC
    android通过USB使用真机调试程序
    pl/sql中实现字符串分割
  • 原文地址:https://www.cnblogs.com/xiaofengzai/p/13495343.html
Copyright © 2011-2022 走看看