Codeforces Round #445 (Div. 2, based on Technocup 2018 Elimination Round 3)

本文介绍了Codeforces Round #445 (Div. 2) 中的三道题目,包括A题ACM ICPC的暴力与优化解法,B题Vlad and Cafes的反向枚举策略,以及C题Petya and Catacombs的贪心解决方案。在A题中,由于忽视数组范围导致WA,通过调整思路成功解决。

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

又是一场unrated比赛,连续熬夜打了两场unrated比赛,不过这场与上场不同,上场是个涨粉的好机会,而似乎是好久没打了,这场却险些大掉分,既然是unrated场,那么就又是题目区分度不大,导致手速成为关键,而这场一道纯暴力却卡a上了,不得不说险些成为血崩场


先来看看这个被卡的a题吧


A. ACM ICPC

思路:将六个数分两组,判断是否可以使两组总和相等

 其实,由于数据范围特别小,完全可以暴力枚举, C(n,n/2)= 24,虽为O(n!)的复杂度,然而由于n特别小,轻松搞定,其实,更暴力的算法O(n^3)= 216也完全可以接受。

然而,为了使自己的算法比较优秀,我就想了更简便的方法,由于6个数分成两组,则任意三个数中,总有两个数在一组,于是C(3,2)=3

然而,万万没想到的事,数组范围的忽视使得这题这种wa,顺间将自己推向了血崩的边缘,猛然发现,赶紧追赶吧

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1e5+10;

int a[6];
int in[10100];

int main()
{
    while(scanf("%d",&a[0])!=EOF)
    {
        /*int sum = a[0];
        for(int i=1;i<6;i++)
        {
            scanf("%d",&a[i]);
            sum += a[i];
        }
        bool yes = false;
        if(sum%2==0)
        {
            if(a[0]+a[1]+a[2]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[1]+a[3]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[1]+a[4]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[1]+a[5]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[2]+a[3]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[2]+a[4]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[2]+a[5]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[3]+a[4]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[3]+a[5]==sum/2)
            {
                yes = true;
            }
            else if(a[0]+a[4]+a[5]==sum/2)
            {
                yes = true;
            }
            if(yes)
            {
                printf("YES\n");
            }
            else
            {
                printf("NO\n");
            }
        }
        else
        {
            printf("NO\n");
        }*/
        memset(in,0,sizeof(in));
        int sum = a[0];
        in[a[0]]++;
        for(int i=1;i<6;i++)
        {
            scanf("%d",&a[i]);
            sum += a[i];
            in[a[i]]++;
        }
        sort(a,a+6);
        if(sum%2==0)
        {
            sum /= 2;
            bool yes = false;
            in[a[0]]--;
            in[a[1]]--;
            //cout << sum-a[0]-a[1] << " " << in[sum-a[0]-a[1]];
            if(in[sum-a[0]-a[1]]>0)
            {
                yes = true;
                //cout << "*";
            }
            in[a[0]]++;
            in[a[1]]++;
            in[a[0]]--;
            in[a[2]]--;
            if(in[sum-a[0]-a[2]]>0)
            {
                yes = true;
                //cout << "**";
            }
            in[a[0]]++;
            in[a[2]]++;
            in[a[1]]--;
            in[a[2]]--;
            if(in[sum-a[1]-a[2]]>0)
            {
                yes = true;
                //cout << "***";
            }
            in[a[1]]++;
            in[a[2]]++;
            if(yes)
            {
                printf("YES\n");
            }
            else
            {
                printf("NO\n");
            }
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}


B. Vlad and Cafes

思路:统计最后未被访问的房间

于是反向枚举,当枚举到n-1个房间时,最后剩余的房间就是最终结果

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 2e5+10;

int a[maxn];
bool in[maxn];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(in,false,sizeof(in));
        int sum = 0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            if(!in[a[i]])
            {
                in[a[i]] = true;
                sum++;
            }
        }
        for(int i=n-1;i>=0;i--)
        {
            if(sum == 1)
            {
                break;
            }
            if(in[a[i]])
            {
                in[a[i]] = false;
                sum--;
            }
        }
        int re;
        for(int i=0;i<maxn;i++)
        {
            if(in[i])
            {
                re = i;
                break;
            }
        }
        printf("%d\n",re);
    }
    return 0;
}




C. Petya and Catacombs

思路:求最小房间数,那就显然是个贪心策略了

对于房间,每次可以随机生成一个数,或者写上次待在这个房间的时间

那么直接贪心就好了,用一个数组记录每个时间点可被访问的情况,初始化为均不可被访问

然后遍历时间,每次遍历后,都将该时间点设置为可被访问

对于每次遍历的结果,如果可访问,即当前时间点访问该时间点的房间,于是不用开辟新房间,并将该时间设置为不可被访问

否则,即必须开辟新房间

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 2e5+10;

bool last[maxn];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int sum = 1;
        memset(last,false,sizeof(last));
        last[0] = true;
        for(int i=1;i<=n;i++)
        {
            int t;
            scanf("%d",&t);
            if(last[t])
            {
                last[t] = false;
            }
            else
            {
                sum++;
            }
            last[i] = true;
        }
        printf("%d\n",sum);
    }
    return 0;
}

后两题由于危机感,还是挺顺畅的,然而第一题有点坑了,细心啊

最后D题,实在太困了,写到睡着,也是无奈,算了,估计这段时间也没时间补这题了,暂时就这样吧

文章地址:http://blog.csdn.net/owen_q/article/details/78564459

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值