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\n");
                return 0;
            }
        }
        else if(a[i]==100){
            if(res&&cnt){
                res--;cnt--;
            }
            else if(cnt>=3){
                cnt-=3;
            }
            else{
                printf("NO\n");
                return 0;
            }
        }
    }
    printf("YES\n");
    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\n",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\n",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;

}

 

posted @ 2019-02-17 17:03  啦啦啦天啦噜  阅读(295)  评论(0编辑  收藏  举报