• Codeforces Round #202 (Div. 2) 题解


    A.Cinema Line

    题意:游客去买票,游客只会拿25,50, 100的钱,刚开始售票处的钱为0,一张门票的价格是25,问你是否有零钱找给这n个游客

    思路:记录现在有多少个25元和多少个50的,如果游客是25元的钱,不需要找钱,50时只能用25的钱找给游客,100时,可以用50+25或者3个25元的,尽量先用50的

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn=1e5+7;
    int a[maxn];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        int cnt=0,res=0;
        for(int i=1;i<=n;i++){
            if(a[i]==25){
                cnt++;
            }
            else if(a[i]==50){
                res++;
                if(cnt){
                    cnt--;
                }
                else{
                    printf("NO
    ");
                    return 0;
                }
            }
            else if(a[i]==100){
                if(res&&cnt){
                    res--;cnt--;
                }
                else if(cnt>=3){
                    cnt-=3;
                }
                else{
                    printf("NO
    ");
                    return 0;
                }
            }
        }
        printf("YES
    ");
        return 0;
    }
    View Code

    B.Color the Fence

    题意:你知道刷每个1-9数字需要多少升颜料,你现在有v升颜料,问你能刷出来最大的数是多少

    思路:数字越长越大,先用花费最少的数字尽可能的使答案边长,然后还会剩下一些燃料,在从高位开始,把高位数字尽可能的改大一点

    代码:

    View Code

    C.Mafia

    题意:有一种游戏,每次游戏都会有一个人做庄家,其他人做玩家,现在有n个人,他们都想做ai次玩家,问你最小需要玩多少次游戏

    思路:二分答案,对于二分的mid,进行判断,让L取为n个玩家中的最大值,记n个人想做玩家的总和为sum,进行mid局游戏,有mid*(n-1)个玩家,判断sum与mid*(n-1)的关系

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    const int maxn=1e5+7;
    int n;
    LL a[maxn];
    LL sum;
    
    bool check(LL x)
    {
        if((n-1)*x>=sum)return true;
        return false;
    }
    int main()
    {
        scanf("%d",&n);
        sum=0;
        LL maxe=-1;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            sum+=a[i];
            maxe=max(maxe,a[i]);
        }
        LL L=maxe,R=0x3f3f3f3f3f3fLL;
        LL ans=0;
        while(L<=R){
            LL mid=(L+R)>>1;
            if(check(mid)){
                R=mid-1;
                ans=mid;
            }
            else L=mid+1;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    D.Apple Tree

    题意:有一棵树,每个叶子节点都有一个权值,问你最少减多少权值可以是整颗树平衡,平衡的定义是一个点的所有儿子权值相等,一个非叶子节点的权值等于他子孩子中叶子节点的权值和

    思路:假设根节点的权值为1,假设根节点有3个儿子,那么每个儿子的重量应该是1/3,一次dfs算出所有叶子节点的权重,因为父节点的权重肯定是子节点的lcm,所以算出所有叶子结点的lcm,在dfs时算出以该叶子节点的权值,整棵树的权值,如果lcm大于最小的权值,表明整棵树都需要被删除,lcm小于最小的权值,因为根节点每次只能+lcm,那么离最小权值的一个数是x-x%lcm,让总和减去它就是最后的答案。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    const int maxn=1e5+7;
    vector<LL>mp[maxn];
    int n;
    LL gcd(LL x,LL y)
    {
        return y==0?x:gcd(y,x%y);
    }
    LL lcm(LL x,LL y)
    {
        return x/gcd(x,y)*y;
    }
    LL a[maxn],val[maxn];
    LL sum,lc,minn;
    bool ok;
    void dfs(int u,int pre)
    {
        if(!ok)return ;
        if(mp[u].size()==1&&pre!=-1){
            minn=min(minn,val[u]*a[u]);
            lc=lcm(lc,val[u]);
            if(lc>minn){
                ok=false;
                return ;
            }
        }
        LL cnt=0;
        for(int i=0;i<mp[u].size();i++){
            int v=mp[u][i];
            if(v==pre)continue;
            cnt++;
        }
        for(int i=0;i<mp[u].size();i++){
            int v=mp[u][i];
            if(v==pre)continue;
            val[v]=val[u]*cnt;
            dfs(v,u);
        }
    }
    int main()
    {
        scanf("%d",&n);
        sum=0;lc=1,minn=0x3f3f3f3f3f3fLL;ok=true;
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]),sum+=a[i];
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            mp[u].push_back(v);
            mp[v].push_back(u);
        }
        val[1]=1;val[0]=1;
        dfs(1,-1);
        if(!ok){
            cout<<sum<<endl;
        }
        else{
            LL ans=sum-minn+minn%lc;
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

    E.Subset Sums

    题意:有长度为n的序列,以及m个集合,然后有两种操作,查询操作是输入? X,表示查询集合x中元素的总和,另一种是修改操作,+ a b表示把集合a中的所有元素加上b,每个集合有numi个元素,输入num个元素表示那些元素属于集合i

    思路:把集合分为两种,元素个数超过sqrt(n)的集合为重集合,不超过sqrt(n)为轻集合

    第i个轻集合更新:直接更新该集合对应的a序列元素,然后更新重集合的总和sum,第j个重集合的sum[j]+=x*(集合i与重集合j交集元素的个数) 

    第i个重集合更新:累加更新值,加在标记上 

    第i个轻集合查询:直接累加该集合对应的a序列元素,然后把重集合延迟的更新累加,即累加上(集合i与重集合j交集元素的个数)*add[j]

    第i个重集合查询:本身的值累加上重集合延迟的更新,即重集合的总和sum[i]+ (集合i与重集合j交集元素的个数) *add[j]

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int maxn=1e5+7;
    int n,m,q;
    LL a[maxn];
    int h[maxn];
    int cnt[maxn][400];
    int res,id[maxn];
    LL sum[maxn];
    LL add[maxn];
    vector<int>mp[maxn],mpp[maxn];
    int main()
    {
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        int num=sqrt(n+0.5),res=0;
        for(int i=1;i<=m;i++){
            int op;
            scanf("%d",&op);
            if(op>=num)h[i]=1,id[++res]=i;
            else h[i]=0;
            for(int j=0;j<op;j++){
                int x;
                scanf("%d",&x);
                mp[i].push_back(x);
                if(h[i])sum[i]+=a[x],mpp[x].push_back(res);
            }
        }
    
        for(int i=1;i<=m;i++){
            for(int j=0;j<mp[i].size();j++){
                int u=mp[i][j];
                for(int k=0;k<mpp[u].size();k++){
                    int v=mpp[u][k];
                    cnt[i][v]++;
                }
            }
        }
        while(q--){
            int k,x;
            char op[5];
            scanf("%s%d",op,&k);
            if(op[0]=='?'){
                LL ans=0;
                if(h[k]){
                    ans=sum[k];
                    for(int i=1;i<=res;i++){
                        ans+=add[id[i]]*cnt[k][i];
                    }
                }
                else{
                    for(int i=0;i<mp[k].size();i++)ans+=a[mp[k][i]];
                    for(int i=1;i<=res;i++)ans+=add[id[i]]*cnt[k][i];
                }
                printf("%lld
    ",ans);
            }
            else{
                scanf("%d",&x);
                if(h[k])add[k]+=x;
                else{
                    for(int i=0;i<mp[k].size();i++)a[mp[k][i]]+=x;
                    for(int i=1;i<=res;i++)sum[id[i]]+=x*cnt[k][i];
                }
            }
        }
        return 0;
    }
    View Code

    #include <bits/stdc++.h>

    using namespace std;

    typedef long long LL;

     

    const int maxn=1e5+7;

    int n,m,q;

    LL a[maxn];

    int h[maxn];

    int cnt[maxn][400];

    int res,id[maxn];

    LL sum[maxn];

    LL add[maxn];

    vector<int>mp[maxn],mpp[maxn];

    int main()

    {

        scanf("%d%d%d",&n,&m,&q);

        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);

        int num=sqrt(n+0.5),res=0;

        for(int i=1;i<=m;i++){

            int op;

            scanf("%d",&op);

            if(op>=num)h[i]=1,id[++res]=i;

            else h[i]=0;

            for(int j=0;j<op;j++){

                int x;

                scanf("%d",&x);

                mp[i].push_back(x);

                if(h[i])sum[i]+=a[x],mpp[x].push_back(res);

            }

        }

     

        for(int i=1;i<=m;i++){

            for(int j=0;j<mp[i].size();j++){

                int u=mp[i][j];

                for(int k=0;k<mpp[u].size();k++){

                    int v=mpp[u][k];

                    cnt[i][v]++;

                }

            }

        }

        while(q--){

            int k,x;

            char op[5];

            scanf("%s%d",op,&k);

            if(op[0]=='?'){

                LL ans=0;

                if(h[k]){

                    ans=sum[k];

                    for(int i=1;i<=res;i++){

                        ans+=add[id[i]]*cnt[k][i];

                    }

                }

                else{

                    for(int i=0;i<mp[k].size();i++)ans+=a[mp[k][i]];

                    for(int i=1;i<=res;i++)ans+=add[id[i]]*cnt[k][i];

                }

                printf("%lld ",ans);

            }

            else{

                scanf("%d",&x);

                if(h[k])add[k]+=x;

                else{

                    for(int i=0;i<mp[k].size();i++)a[mp[k][i]]+=x;

                    for(int i=1;i<=res;i++)sum[id[i]]+=x*cnt[k][i];

                }

            }

        }

        return 0;

    }

     

  • 相关阅读:
    爱因斯坦IQ题
    微软操作系统的版本分类方法
    C++的辅助工具介绍
    让Dictionary key 支持自定义对象
    正则表达式匹配可能包括任意长度的任意空白的任意字符串(最短匹配)
    linq 对象转换
    "System.Data.SqlServerCe.SqlCeException: 数据库文件大于配置的最大数据库大小。该设置仅在第一次并发数据库连接后生效"解决方案
    Windows XP远程桌面端口更改
    Unicode与UTF8互转(C语言实现)
    VS2005+WinXPDDK+DDKWizard配置驱动开发环境
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/10391815.html
Copyright © 2020-2023  润新知