AtCoder Beginner Contest 330

这篇具有很好参考价值的文章主要介绍了AtCoder Beginner Contest 330。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

A - Counting Passes (abc330 A)

题目大意

给定\(n\)个学生的分数,以及及格分 \(x\),问多少人及格了。

解题思路

依次判断即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, l;
    cin >> n >> l;
    int ans = 0;
    while (n--) {
        int x;
        cin >> x;
        ans += (x >= l);
    }
    cout << ans << '\n';

    return 0;
}



B - Minimize Abs 1 (abc330 B)

题目大意

回答\(n\)个问题,每个问题给定 \(a,l,r\),问函数 \(f(x) = |x - a|\)\([l,r]\)的最小值。

解题思路

全定义域下,最小值显然在\(x=a\)取得。绝对值函数图像是\(V\)型。

现在限定在 \([l,r]\),则分 \(a \leq l, a \geq r, l < a < r\)三种情况分别讨论极值即可。即分别在\(x=l, x=r, x=a\)取得最小值。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, l, r;
    cin >> n >> l >> r;
    while (n--) {
        int a;
        cin >> a;
        if (a <= l)
            cout << l << ' ';
        else if (a >= r)
            cout << r << ' ';
        else
            cout << a << ' ';
    }

    return 0;
}



C - Minimize Abs 2 (abc330 C)

题目大意

给定\(d\),问函数 \(f(x,y) = |x^2 + y^2 - d|\)的最小值。

解题思路

枚举\(x\)的取值,范围是\([1,2e6]\),然后得 \(y^2 = abs(d - x * x)\),分别取 \(y_1 = \lfloor \sqrt{y^2} \rfloor, y_2 = \lceil \sqrt{y^2} \rceil\),由于会有一正一负的情况(\(x^2 + y_1^2 \leq d, x^2 + y_2^2 \geq d\)),取\(\min(f(x, y_1), f(x, y_2))\),对所有 \(x\)取最小值即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    LL d;
    cin >> d;
    int up = 2e6;
    LL ans = 1e18;
    for (int i = 0; i <= up; ++i) {
        LL x = 1ll * i * i;
        LL y = abs(d - x);
        LL y1 = floor(sqrt(y)), y2 = ceil(sqrt(y));
        ans = min({ans, abs(x + y1 * y1 - d), abs(x + y2 * y2 - d)});
    }
    cout << ans << '\n';

    return 0;
}



D - Counting Ls (abc330 D)

题目大意

给定一个包含ox的二维矩阵。问所有的满足下述条件的三元组下标数量。

  • 这三个三元组对应的符号都是o
  • 恰有两个三元组同一行。
  • 恰有两个三元组同一列。

解题思路

三元组组成的图形都是形如

oo oo o   o
o   o oo oo

由此我们枚举转折点的o,由这个o组成的图形的数量就是\((row[i] - 1) \times (col[j] - 1)\) ,其中\(row[i],col[j]\)表示这个 o所在行和列的o的数量。累计所有的这些o即是答案。

注意答案可能会超int

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    vector<string> s(n);
    for (auto& i : s) {
        cin >> i;
    }
    vector<int> col(n), row(n);
    for (int i = 0; i < n; ++i) {
        row[i] = ranges::count(s[i], 'o');
        for (int j = 0; j < n; ++j)
            col[i] += (s[j][i] == 'o');
    }
    LL ans = 0;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j) {
            if (s[i][j] == 'o') {
                ans += 1ll * (row[i] - 1) * (col[j] - 1);
            }
        }
    cout << ans << '\n';

    return 0;
}



E - Mex and Update (abc330 E)

题目大意

给定一个数组\(a\),进行如下操作。

每次操作 令\(a_i = x\)。然后输出 \(mex(a)\)

\(mex(a)\)表示数组\(a\)未出现的最小非负整数。

解题思路

考虑如何求出一个数组的\(mex\),我们可以记 \(visit[i]\)表示数字 \(i\)的出现次数,那每次求 \(mex\)可以从小到大遍历该数组,找到第一个出现次数为\(0\)的下标即是答案。

但这复杂度可能会高达 \(O(n)\),考虑更快速的方法,我们可以用 \(set\)储存 \(visit\)数组中值为 \(0\)(未出现的数)下标,这样 \(set\)的最小值就是答案。

\(a_i=x\)时,相当于把原来的 \(a_i\)删掉,即 \(visit[a_i]--\),然后把 \(x\)加进来,即 \(visit[x]++\),如果 \(visit[a_i]\)变为 \(0\),则说明 \(a_i\)没有出现,将其插入到 \(set\)中。同时 \(visit[x]\)变为 \(1\),说明 \(x\)出现了,从 \(set\)中删去。

这样就可以动态维护 \(mex\)值,其复杂度都是 \(O(log)\)

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, q;
    cin >> n >> q;
    map<int, int> cnt;
    vector<int> ini(n + 1);
    iota(ini.begin(), ini.end(), 0);
    set<int> mex(ini.begin(), ini.end());
    vector<int> a(n);
    auto insert = [&](int i) {
        int x = a[i];
        cnt[x]++;
        if (cnt[x] == 1)
            mex.erase(x);
    };
    auto remove = [&](int i) {
        int x = a[i];
        cnt[x]--;
        if (cnt[x] == 0)
            mex.insert(x);
    };
    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        a[i] = x;
        insert(i);
    }
    while (q--) {
        int pos, x;
        cin >> pos >> x;
        --pos;
        remove(pos);
        a[pos] = x;
        insert(pos);
        cout << *mex.begin() << '\n';
    }

    return 0;
}



F - Minimize Bounding Square (abc330 F)

题目大意

二维平面,点,可进行最多\(k\)次操作,每次操作将一个点上下左右移动一格。点可以重叠。

问进行操作后,能将所有点覆盖的正方形的边长的最小值。

解题思路

两个维度相互独立,我们可以分别考虑每个维度。

考虑一维情况下,如果我们固定覆盖的线段长度,会发现比较好做。

注意到如果边长越大,我们需要的移动次数越少,可行的可能性就越高,相反,边长越小,需要移动的次数越多,可行的可能性就越低。这里有一个单调性,因此我们可以二分最终的边长。

边长固定了,考虑到最优情况下,覆盖的线段必定有一端点上的点是从来没移动过的,因此我们可以枚举这个作为边界的点。然后计算需要移动的次数。

坐标从小到大考虑,可以用双指针维护移动次数(一个前缀坐标和与一个后缀坐标和)。注意需要分别枚举作为左端点的点和作为右端点的点。

两个维度分别取所需移动次数的最小值,其和不超过\(k\)则边长可行。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    LL k;
    cin >> n >> k;
    vector<LL> x(n), y(n);
    for (int i = 0; i < n; ++i)
        cin >> x[i] >> y[i];
    ranges::sort(x);
    ranges::sort(y);
    vector<LL> invx = x, invy = y;
    ranges::reverse(invx);
    ranges::reverse(invy);
    int l = -1, r = 1e9 + 1;
    auto ok = [&](int len, vector<LL>& p, int sign = 1) {
        LL sufsum = accumulate(p.begin(), p.end(), 0ll);
        LL presum = 0;
        LL minn = 1e18;
        int r = 0;
        for (int i = 0; i < n; ++i) {
            while (r < n && abs(p[r] - p[i]) <= len) {
                sufsum -= p[r];
                ++r;
            }
            LL cnt = abs(p[i] * i - presum) +
                     abs(sufsum - (p[i] + sign * len) * (n - r));
            minn = min(cnt, minn);
            presum += p[i];
        }

        return minn;
    };
    auto check = [&](int len) {
        return min(ok(len, invx, -1), ok(len, x)) +
                   min(ok(len, invy, -1), ok(len, y)) <=
               k;
    };
    while (l + 1 < r) {
        int mid = (l + r) >> 1;
        if (check(mid))
            r = mid;
        else
            l = mid;
    }
    cout << r << '\n';

    return 0;
}



G - Inversion Squared (abc330 G)

题目大意

给定一个数组\(a\),仅包含 \(-1\)或者 \([1,n]\),其中 \([1,n]\)中的数最多只出现一次。

计算满足以下条件的排列的逆序对的平方和。

  • \(a_i \neq -1 => p_i = a_i\)。(即将 \(-1\)替换成其他数,使得形成一个排列)

解题思路

<++>文章来源地址https://www.toymoban.com/news/detail-747126.html

神奇的代码



到了这里,关于AtCoder Beginner Contest 330的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AtCoder Beginner Contest 314

    怎么好多陌生单词 审核怎么这么逆天,半小时还没审完 给定 (pi) 的值以及数 (n) ,要求保留 (n) 位小数输出,不四舍五入。 字符串形式储存然后截取末尾即可。 神奇的代码 (n) 个人玩轮盘赌游戏,简单说就是一个转盘有 (37) 个数字以及一个箭头,箭头会等概率停在某

    2024年02月13日
    浏览(28)
  • AtCoder Beginner Contest 349

    (n) 个人游戏,每局有一人 (+1) 分,有一人 (-1) 分。 给定最后前 (n-1) 个人的分数,问第 (n) 个人的分数。 零和游戏,所有人总分是 (0) ,因此最后一个人的分数就是前 (n-1) 个人的分数和的相反数。 神奇的代码 对于一个字符串,如果对于所有 (i geq 1) ,都有恰好

    2024年04月13日
    浏览(46)
  • AtCoder Beginner Contest 344

    给定一个字符串,包含两个 | ,将 | 和两个 | 之间的字符消去。 按照题意模拟即可。 Python 比较简洁。 神奇的代码 给定 (n) 个数,倒序输出。 储存这 (n) 个数,然后倒着输出即可。 神奇的代码 给定三个数组 (a,b,c) ,回答 (q) 次询问。 每次询问,给定 (x) ,问能否从三

    2024年03月10日
    浏览(30)
  • AtCoder Beginner Contest 322

    给定一个字符串,找到最先出现 ABC 的位置。 直接查找判断即可。 神奇的代码 给定字符串 s 和 t ,问 s 是不是 t 的前缀和后缀。 根据前后缀定义判断即可。这里试了下 python 神奇的代码 (n) 天,有 (m) 天会放烟花。 问每一天,距离未来最近的放烟花的天数。 两个双指针一

    2024年02月08日
    浏览(20)
  • AtCoder Beginner Contest 342

    给定一个字符串,两个字符,其中一个只出现一次,找出它的下标。 看第一个字符出现次数,如果是 (1) 则就是它,否则就是 不是它的字符 。 神奇的代码 一排人。 (m) 个询问,每个询问问两个人,谁在左边。 记录一下每个人的下标,然后对于每个询问比较下标大小即可

    2024年03月09日
    浏览(62)
  • AtCoder Beginner Contest 318

    咕咕咕,总力战还没打,凹不过卷狗,躺了.jpg 给定 (n, m, p) ,问有多少个 (i) 满足 (0 m+pi leq n) 减去初始的 (m) ,剩下的就是看 (p) 的倍数个数。 神奇的代码 一个二维空间,有 (n) 个矩形覆盖。 问有多大的空间被覆盖了。重复覆盖算一次。 空间大小只有 (100) ,矩形

    2024年02月10日
    浏览(29)
  • AtCoder Beginner Contest 306

    给定一个字符串,将每个字符输出两次。 模拟即可。 神奇的代码 给定一个从低位开始的二进制串,将其转为十进制。 注意有 (64) 位,得用 unsigned long long 。 神奇的代码 给定一个 (1 sim n) 都出现三次的数组 (a) 。 定义 (f(x)) 表示 (x) 第二次出现在 (a) 的位置。 按照位

    2024年02月09日
    浏览(25)
  • AtCoder Beginner Contest 319

    给定rating前10的选手名字和对应分数。 给定名字,问对应分数。 复制一下,建个数组,然后一个一个判断即可。 Python 更好写一点。 神奇的代码 给定 (n) ,生成一个长度为 (n+1) 的字符串 (s) ,其中 (s_i) ( (i) 从 (0) 开始)为 (1 sim 9) 中最小的 (j) 使得 (i) 是 (f

    2024年02月09日
    浏览(18)
  • AtCoder Beginner Contest 313

    貌似这次很难,还好去吃烧烤了 发现原来G就是个类欧几里德算法,参考abc283 ex,更了个G 给定 (n) 个数 (a_i) ,问第一个数要成为唯一的最大的数,应该加多少。 找到后面的最大的数 (m) ,答案就是 (max(0, m + 1 - a_0)) 。 神奇的代码 给定 (m) 条关于 (n) 个数的大小关系,

    2024年02月14日
    浏览(28)
  • AtCoder Beginner Contest 309

    感觉F写了个乱搞做法 给定一个 (3 times 3) 的网格,以及两个数字。 问这两个数字是否 水平相邻 。 求出两个数字的横纵坐标,看是否横坐标相同,纵坐标差一即可。 读题不仔细,开题就WA了。 神奇的代码 给定一个矩形。将最外围的数字顺时针旋转一格。 可以模拟一个指针

    2024年02月13日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包