Codeforces Round #661 Div3 前四题(咕

目录

  • A - Remove Smallest
  • B - Gifts Fixing
  • C - Boats Competition
  • D - Binary String To Subsequences

A - Remove Smallest

思路:

  • 从小到大排序,相邻两个比较,只要有相邻两个数相差超过1的就不可能只剩一个

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define pi acos(-1)
#define N 5010
using namespace std;

int a[N];

int main()
{
    int T, n;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
        }
        sort(a, a + n);
        bool flag = 0;
        for(int i = 1; i < n; i++)
        {
            if(a[i] - a[i - 1] > 1)
            {
                flag = 1;
                break;
            }
        }
        if(flag)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}

B - Gifts Fixing

思路:

  • 找到a、b数组中最小的数amin和bmin,数组中所有数字都减去amin和bmin,就是多出来要吃掉的糖果和橘子。至于计算第i份礼物要吃几次,就是此时ai和bi中较大的那个数。
  • 疑问:一个橘子不够管饱吗?不是很懂

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define pi acos(-1)
#define N 5010
using namespace std;

typedef long long ll;

ll a[N], b[N];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        int amin = INF, bmin = INF;
        for(int i = 0; i < n; i++)
        {
            scanf("%lld", &a[i]);
            if(a[i] < amin)
                amin = a[i];
        }
        for(int i = 0; i < n; i++)
        {
            a[i] -= amin;
        }
        for(int i = 0; i < n; i++)
        {
            scanf("%lld", &b[i]);
            if(b[i] < bmin)
                bmin = b[i];
        }
        for(int i = 0; i < n; i++)
        {
            b[i] -= bmin;
        }
        ll ans = 0;
        for(int i = 0; i < n; i++)
        {
            if(a[i] < b[i])
                ans += b[i];
            else
                ans += a[i];
        }
        printf("%lld\n", ans);
    }
}

C - Boats Competition

开始C题WA傻了,怎么都找不到问题,然后重新写了一份完全暴力的过了。最后检查前面那份的时候发现,是因为第一份写的初始化范围是
for(int i = 0; i <= n; i++) num[i] = 0
暴力那份用的memset
重新看了一下题,把n改成了2 * n,就过了。这要是赛场上C题 WA 8发,后果不堪设想。。。

思路:

  1. 暴力:本题数据范围小,可以直接从2到2 * n枚举和的情况,计算每种情况能凑成的对数,取最大值
  2. 优化:两数之和必然大于等于所有数中最小的数,就可以从min * 2开始枚举

代码(优化版):

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define pi acos(-1)
#define N 1100
using namespace std;

typedef long long ll;

int a[N];
int num[N];
bool vis[N];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        int minn = INF;
        int maxx = -1;
        int cnt = 0;
        scanf("%d", &n);
        for(int i = 0; i <= 2 * n; i++)
            num[i] = 0;
        for(int i = 0; i < n; i++)
        {
            int x;
            scanf("%d", &x);
            if(minn > x)
                minn = x;
            if(maxx < x)
                maxx = x;
            if(num[x] == 0)
                a[cnt++] = x;
            num[x]++;
        }
        int ans = 0;
        for(int sum = minn * 2; sum <= maxx * 2; sum++)
        {
            int tmp = 0;
            for(int i = 0; i < cnt; i++)
            {
                if(sum - a[i] == a[i])
                {
                    tmp += num[a[i]];
                    continue;
                }
                tmp += num[sum - a[i]] < num[a[i]] ? num[sum - a[i]] : num[a[i]];
            }
            ans = tmp / 2 > ans ? tmp / 2 : ans;
        }
        printf("%d\n", ans);
    }
    return 0;
}

代码(未优化版):

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define pi acos(-1)
#define N 1100
using namespace std;

typedef long long ll;

int a[N];
int num[N];
bool vis[N];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        for(int i = 0; i <= 2 * n; i++)
            num[i] = 0;
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
            num[a[i]]++;
        }
        ll ans = -1;
        for(int sum = 2; sum <= 2 * n; sum++)
        {
            ll tmp = 0;
            for(int i = 1; i <= sum; i++)
                tmp += min(num[i], num[sum - i]);
            ans = max(tmp / 2, ans);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

D - Binary String To Subsequences

还是没在赛场上写出来。。。
思路:

  • 参考:CF1399-Codeforces Round #661 (Div. 3)-D. Binary String To Subsequences(构造、模拟)
  • 用两个队列q1、q0记录当前所有01串的信息,结尾为0记录在q0串,结尾为1记录在q1串
  • 用vector记录每个元素所在01串编号
  • 选取str[i],如果是0,就去看队列q1里是否有元素;没有元素就新创建一个链,有元素就接在该链的末尾;是1的情况以此类推

代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define pi acos(-1)
#define N 1000100
using namespace std;

typedef long long ll;
char str[N];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        scanf("%s", str);
        ll cnt = 0;
        queue <ll> q0, q1;
        vector <ll> ans;
        for(int i = 0; i < n; i++)
        {
            if(str[i] == '0')
            {
                if(q1.empty())
                    ans.push_back(cnt++);
                else
                {
                    ans.push_back(ans[q1.front()]);
                    q1.pop();
                }
                q0.push(i);
            }
            else
            {
                if(q0.empty())
                    ans.push_back(cnt++);
                else
                {
                    ans.push_back(ans[q0.front()]);
                    q0.pop();
                }
                q1.push(i);
            }
        }
        printf("%lld\n", cnt);
        for(auto i : ans)
        {
            printf("%lld ", i + 1);
        }
        printf("\n");
    }
    return 0;
}

赛后小结:

  • 还好昨天没有熬夜打(bushi
  • D题又是想得出不会实现
  • C题走死胡同了,简单的一个初始化问题最后通篇代码换掉,下次还是要注意范围

多多包涵,努力进步。

你可能感兴趣的:(CF补题总结)