Codeforces Round #202 (Div. 2) (A、B、C、D)

博主分享了在Codeforces Round #202 (Div. 2)比赛中的经历和四道题目——A. Cinema Line、B - Color the Fence、C - Mafia、D - Apple Tree的解题思路。A题通过模拟解决找零问题;B题通过优化策略确定能写出的最大数字;C题通过二分搜索确定最少的游戏局数;D题利用树的结构和分支数找到平衡所需的最小减权值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

           这场比赛发挥的不太好吧,当时只做了两题,第三题当时已经想到正解了,但不知发什么神经去想别的解法了。。。果然晚上的状态不好啊。

 

A. Cinema Line

     非常水……一队人排队买票,每个人只有25、50和100的面值的钱,问买票的人最开始手里没有钱,能否给每个买票的人找钱。直接模拟即可~

 

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    while(~scanf("%d",&n))
    {
        int a,b,tmp;
        a=b=0;
        bool flag=true;
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&tmp);
            if(tmp==25)
              a++;
            else if(tmp==50)
            {
                b++;
                if(a>0) a--;
                else flag=false;
            }
            else
            {
                if(b>0)
                {
                    if(a>0) b--,a--;
                    else flag=false;
                }
                else
                {
                    if(a>2) a-=3;
                    else flag=false;
                }
            }
        }
        if(flag) puts("YES");
        else puts("NO");
    }
    return 0;
}


 

 

 

B - Color the Fence

       你有v升油漆,可以用这些油漆写数字,给出(1~9)每个数字需要使用的油漆的量,问能写出的最大数字是多少。

       我感觉这题很简单啊,但是不知为什么到最后有不少人这题都挂了。最直观的想法就是让每个数字尽量多嘛,这样的话先找出使用油漆最少并且值尽量大的数字,先尽量写这些数字,直到不能写为止,这时有可能还有剩余的油漆,这时只要从最开始看每一位是否能被更大的数字替代就行了。

 

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=1000000+10;
struct Node
{
    int cost,num;
    bool operator < (const Node &a) const
    {
        return (cost==a.cost&&num>a.num)||(cost<a.cost);
    }
};
Node node[10];
int res[maxn],c[10];
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int v;
    while(~scanf("%d",&v))
    {
        for(int i=0;i<9;++i)
        {
            scanf("%d",&node[i].cost);
            node[i].num=i+1;
            c[i+1]=node[i].cost;
        }
        sort(node,node+9);
        int f=node[0].num;
        int cnt=v/node[0].cost;
        int r=v-cnt*node[0].cost;
        bool find;
        if(cnt==0)
        {
            printf("-1\n");
            continue;
        }
        while(r>0&&cnt>0)
        {
            find=false;
            for(int i=9;i>0;--i)
            {
                if(i>f&&r+node[0].cost>=c[i])
                {
                    find=true;
                    printf("%d",i);
                    r-=(c[i]-node[0].cost);
                    cnt--;
                    break;
                }
            }
            if(!find) break;
        }
        for(int i=0;i<cnt;++i)
          printf("%d",f);
        printf("\n");
    }
    return 0;
}


 

 

C - Mafia

       n个人一起玩游戏,每一轮游戏必须有一个主持人,给出每个人想玩游戏的局数(不当主持人),问至少要多少局比赛才能满足每个人的要求。

       n只有10^5,所以可以二分局数,判断这个局数是否能满足所有人要求就行了……

 

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int num[maxn];
ll sum,maxL;
int n;
bool check(ll m)
{
    ll cnt=0;
    for(int i=0;i<n;++i)
      cnt+=(m-num[i]);
    return cnt>=maxL&&cnt>=m;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(~scanf("%d",&n))
    {
        ll L=0,R=Inf;
        sum=0;maxL=0;
        for(int i=0;i<n;++i)
        {
            scanf("%d",&num[i]);
            maxL=max(maxL,(ll)num[i]);
            sum+=num[i];
        }
        L=maxL;R=sum;
        ll m;
        while(L<R)
        {
            m=(L+R)>>1;
            if(check(m))
              R=m;
            else
              L=m+1;
        }
        printf("%I64d\n",L);
    }
    return 0;
}


 

 D - Apple Tree 

 

        给出一棵树,树上每个叶子节点都有一个权值,给出平衡的定义:一个树平衡,当且仅当对于每一个节点u,都有它的所有的子树,都有相同的权值。问至少要减掉多少权值才能让整棵树平衡。

       用val[u]代表节点u子树的总和,fz[u]代表u的总分支数(注意这个分支数并不是实际的分支数)。

       看下面的图,这是一个已经处理完的图,每个结点旁边红色的是对应的val[u]的值,紫色的是对应的fz[u]的值。最下面一层很显然是对的,到了第二层,这些结点的权值已经相等了(若不相等需要把他们变为相等),可以发现1结点每次要在其子树中减少权值的话,为了保持平衡,2、3、4这三个分分支要减去相等的值,但这三个结点有些值是不能减的,比如2和3结点,如果要同时减2,可以看到3结点减2是不可能让子树平衡的,因此,每次减的值只能是所有子树分支的最小公倍数,另外还要保证每个分支减的数相同,那么每次要减的最小的数就是:所有子树分支的最小公倍数×分支数。这也就相当于u结点有这些个分支。

      

 

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
struct Edge
{
    int v,next;
};
Edge edges[maxn<<1];
int head[maxn],nEdge;
int w[maxn];
void AddEdge(int u,int v)
{
    nEdge++;
    edges[nEdge].v=v;
    edges[nEdge].next=head[u];
    head[u]=nEdge;
}
ll val[maxn],fz[maxn];
ll gcd(ll a,ll b)
{
    ll c;
    while(b!=0)
    {
        c=b;
        b=a%b;
        a=c;
    }
    return a;
}
ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}
void dfs(int u,int fa)
{
    ll a=-1,x=-1,b,y;
    int child=0;
    for(int k=head[u];k!=-1;k=edges[k].next)
    {
        int v=edges[k].v;
        if(v==fa) continue;
        child++;
        dfs(v,u);
        if(a==-1)
          a=val[v],x=fz[v];
        else
        {
            b=val[v];y=fz[v];
            if(a==0||b==0)
            {
                a=0;
                continue;
            }
            ll c=min(a,b)-min(a,b)%lcm(x,y);
            x=lcm(x,y);
            a=c;
        }
    }
    if(child==0)
    {
        val[u]=w[u];
        fz[u]=1;
    }
    else
    {
        val[u]=a*child;
        fz[u]=x*child;
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    while(~scanf("%d",&n))
    {
        memset(head,0xff,sizeof(head));
        nEdge=-1;
        ll sum=0;
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&w[i]);
            sum+=w[i];
        }
        int u,v;
        for(int i=1;i<n;++i)
        {
            scanf("%d%d",&u,&v);
            AddEdge(u,v);
            AddEdge(v,u);
        }
        dfs(1,-1);
        sum-=val[1];
        printf("%I64d\n",sum);
    }
    return 0;
}


 

       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值