首页 > 其他分享 >AtCoder Beginner Contest 364 补题记录(A~F)

AtCoder Beginner Contest 364 补题记录(A~F)

时间:2024-07-28 11:07:02浏览次数:13  
标签:std AtCoder Beginner int GLIBCXX long 补题 include define

VP 五十八分钟苏童流体。好耶

A

#define GLIBCXX_DEBUG
#include <iostream>
#include <cstring>
#include <cstdio>
#define int long long
const int N = 500100;
std::string s[N];
signed main() {
    int n, cnt = 1;
    scanf("%lld", &n);
    for (int i = 1; i <= n; ++i)
        std::cin >> s[i];
    for (int i = 2; i < n; ++i) {
        if (s[i] == "sweet" && s[i - 1] == "sweet") {
            printf("No\n");
            return 0;
        }
    }
    puts("Yes");
    return 0;
}

B

直接模拟即可。

#define GLIBCXX_DEBUG
#include <iostream>
#include <cstring>
#include <cstdio>
#define int long long
const int N = 500100;
char s[510][510];
signed main() {
    int n, m;
    scanf("%lld%lld", &n, &m);
    int x, y;
    scanf("%lld%lld", &x, &y);
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            std::cin >> s[i][j];
    std::string xx;
    std::cin >> xx;
    for (auto &v : xx) {
        if (v == 'U') {
            if (x > 1 && s[x - 1][y] == '.')
                --x;
        } else if (v == 'D') {
            if (x < n && s[x + 1][y] == '.')
                ++x;
        } else if (v == 'L') {
            if (y > 1 && s[x][y - 1] == '.')
                --y;
        } else {
            if (y < m && s[x][y + 1] == '.')
                ++y;
        }
    }
    std::cout << x << ' ' << y << '\n';
    return 0;
}

C

简单贪心。容易发现甜度和咸度互相独立,因此分类甜度最少多少次,咸度最少多少次即可。排一下序就可以求出答案。

时间复杂度为 \(O(n\log n)\)。

#define GLIBCXX_DEBUG
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define int long long
const int N = 500100;
int a[N], b[N];
signed main() {
    int n, x, y;
    std::cin >> n >> x >> y;
    for (int i = 1; i <= n; ++i)
        std::cin >> a[i];
    for (int i = 1; i <= n; ++i)
        std::cin >> b[i];
    std::sort(a + 1, a + n + 1, std::greater<>());
    std::sort(b + 1, b + n + 1, std::greater<>());
    int c1 = 0, c2 = 0, s1 = 0, s2 = 0;
    for (int i = 1; i <= n; ++i) {
        s1 += a[i];
        ++c1;
        if (s1 > x) break;
    }
    for (int i = 1; i <= n; ++i) {
        s2 += b[i];
        ++c2;
        if (s2 > y) break;
    }
    std::cout << std::min(c1, c2) << '\n';
    return 0;
}

D

二分套二分板子。考虑对于每一个询问二分距离,然后两个二分分别二分出左边和右边最多可以选择多少个点,判断选择的点数是否超过了 \(k\) 即可。稍微有一点点细节。时间复杂度为 \(O(n\log^2n)\)。不知道有没有单 \(\log\) 做法。

#define GLIBCXX_DEBUG
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define int long long
const int N = 500100;
int a[N], b[N];
signed main() {
    int n, x, y;
    std::cin >> n >> x >> y;
    for (int i = 1; i <= n; ++i)
        std::cin >> a[i];
    for (int i = 1; i <= n; ++i)
        std::cin >> b[i];
    std::sort(a + 1, a + n + 1, std::greater<>());
    std::sort(b + 1, b + n + 1, std::greater<>());
    int c1 = 0, c2 = 0, s1 = 0, s2 = 0;
    for (int i = 1; i <= n; ++i) {
        s1 += a[i];
        ++c1;
        if (s1 > x) break;
    }
    for (int i = 1; i <= n; ++i) {
        s2 += b[i];
        ++c2;
        if (s2 > y) break;
    }
    std::cout << std::min(c1, c2) << '\n';
    return 0;
}

E

这不 AT_dp_e。最简单的思路是 \(f_{i,j,k}\) 表示当前选择前 \(i\) 个菜肴,甜度为 \(j\),咸度为 \(k\) 最多可以选择多少个菜肴。但是显然过不去。考虑交换状态。设 \(f_{i,j,k}\) 表示当前选择前 \(i\) 个菜肴,选了 \(j\) 个菜肴,当前甜度为 \(k\) 的最小咸度为多少。式子显然。

时间复杂度为 \(O(n^2\min(X,Y))\)。

#define GLIBCXX_DEBUG
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
// #define int long long
const int N = 500100;
int a[N], b[N], f[83][83][10010];
signed main() {
    std::ios_base::sync_with_stdio(0);
    std::cin.tie(0);
    int n, x, y;
    std::cin >> n >> x >> y;
    for (int i = 1; i <= n; ++i)
        std::cin >> a[i] >> b[i];
    memset(f, 0x3f, sizeof f);
    f[0][0][0] = 0;
    // f[i][j][k] 表示当前吃了前 i 个菜肴,选择 j 个菜肴,当前甜度为 k 的最小咸度
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= i; ++j)
            for (int k = a[i]; k <= x; ++k)
                for (int p = 0; p < i; ++p)
                    f[i][j][k] = std::min(f[i][j][k], f[p][j - 1][k - a[i]] + b[i]);
    int res = 0;
    for (int i = 1; i <= n; ++i)
    for (int j = 0; j <= n; ++j)
        for (int k = 0; k <= x; ++k)
            if (f[i][j][k] <= y)
                res = std::max(res, j);
    if (res != n)
        ++res;
    std::cout << res << '\n';
    return 0;
}

F

首先把所有的边离线下来按照代价从小到大排序。

然后对于每一条边 \(l\sim r\),若其前面的所有的边都已经加入最小生成树中,则可以考虑维护任意相邻的两个点 \(i,i+1\) 之间的连通性。每一次操作完毕之后一定贪心的让 \(l\sim r\) 中所有的点都连通,也就是说 \(l\sim r-1\) 之间的边全部删除。

直接暴力枚举显然不可行。因此考虑用一个 set 来维护答案,每一次用 lower_bound 找到其下一次要删除的边并将其刹删除。很明显每一条边最多只会被删除 \(1\) 次。因此时间复杂度为 \(O(n\log n)\) 可以通过。

#define GLIBCXX_DEBUG
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <algorithm>
#define int long long
const int N = 2000100;
struct awa {
    int a, b, c;
} wx[N];
bool operator<(const awa &l, const awa &r) {
    return l.c < r.c;
}
int la[N];
signed main() {
    int n, q;
    scanf("%lld%lld", &n, &q);
    for (int i = 1; i <= q; ++i)
        scanf("%lld%lld%lld", &wx[i].a, &wx[i].b, &wx[i].c);
    std::sort(wx + 1, wx + q + 1);
    std::set<int> se;
    for (int i = 1; i <= n; ++i)
        se.insert(i), la[i] = i;
    int cost = 0;
    for (int i = 1; i <= q; ++i) {
        auto it = se.lower_bound(wx[i].a);
        int pos = la[*it], cnt = 0, tm;
        for (; it != se.end() && wx[i].b >= la[*it]; se.erase(tm))
            tm = *it, ++it, ++cnt;
        se.insert(tm), la[tm] = pos;
        cost += cnt * wx[i].c;
    }
    if (se.size() == 1)
        printf("%lld\n", cost);
    else
        puts("-1");
}

标签:std,AtCoder,Beginner,int,GLIBCXX,long,补题,include,define
From: https://www.cnblogs.com/yhbqwq/p/18327968

相关文章

  • AtCoder Beginner Contest 364
    A-GluttonTakahashi(abc364A)题目大意给定\(n\)个字符串,问是否有两个相邻的sweet。解题思路遍历判断当前字符串与上一个字符串是否都为sweet即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_......
  • AtCoder Beginner Contest 364 复盘
    AtCoderBeginnerContest364当你发现你的做法假了时,再看看题目的时限和空限,你就有可能发现,你的做法真了。本场口胡出了\(5\)题的正解,但是只写出了\(3\)题。弱弱又智智。A-GluttonTakahashi&B-GridWalk&C-MinimumGlutton签到D-K-thNearest算口胡出半......
  • AtCoder Beginner Contest 362
    题目链接:AtCoderBeginnerContest362A.BuyaPentag:签到B.RightTriangletag:模拟C.RightTriangletag:贪心Description:给定\(n\)对整数\(l_i,r_i\);求一个整数序列,满足\(l_i<=x_i<=r_i\),且\(\sum_{i}^{n}x_i=0\);如果没有则输出\(-1\)。Solution:先判断是否有解,令......
  • AtCoder Beginner Contest 363
    上周去玩了(逃A-PilingUp(abc363A)题目大意给定分数,问晋级还差多少分。分别到\(100,200,300\)分能晋级。解题思路找到第一个大于当前分数的,其差即为答案。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){io......
  • Codeforces Round 962 (Div. 3) 补题记录(A~G)
    这场Div.3难度高于平时。A#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=500100;inta[N];signedmain(){intT;scanf("%lld",&T);while(T--){intn;scanf("%lld",......
  • AtCoder Beginner Contest 360 题解(C-E)
    C-MoveIt题目链接:C-MoveIt题目大意:有\(N\)个盒子和\(N\)个物品编号为\(1-N\),物品\(i\)在盒子\(A_i\)中,重量为\(W_i\),你可以进行一种操作将盒子中的一件物品移动到其他任意盒子中,代价为\(W_i\),求使得所有盒子中只存在一件物品的最小操作代价。题解:贪心,可以发现......
  • 平邑2024高算(补题)
    Day1risk题目描述解法考虑最后的集结,不妨考虑找出所有集结过程中可能经过的边,不难发现是一棵树,所以答案就是最小生成树。代码点击查看代码structnode{ intu,v,w;}e[3000001];intn,m;intfa[3000001];intfind(intx){ returnx==fa[x]?fa[x]:fa[x]=find(......
  • [atcoder utpc2023_p] Priority Queue 3
    PriorityQueue3题意:有一个小根堆和\(1\)~\(n\)个数,以及一个操作序列,+表示\(push\),-表示\(pop\),\(pop\)有\(m\)次,问你有多少种插入顺序使得最后的pop集合与给出的的数字集合\(Y\)相同。首先有个浅显的发现:对于不在\(Y\)集合中的数,可选范围形如一个阶梯,换句话......
  • Solution - Atcoder Xmas2019E Sum of f(n)
    考虑\(F(n)=\sum\limits_{i=1}^nf_i=\sum\limits_{i=1}^n\sum\limits_{p\in\mathbb{P},k\ge1}[p^k|i]=\sum\limits_{p\in\mathbb{P},k\ge1}\lfloor\frac{n}{p^k}\rfloor\)。对于这个\(\lfloor\frac{n}{x}\rfloor\),一个比较经典的想法就是考虑对其......
  • Solution - Atcoder Xmas2019D Sum of (-1)^f(n).md
    对于\(f(i)=(-1)^{\sum\limits_jc_j}(i=\prod\limits_jp_j^{c_j}(p_j\in\mathbb{P}))\),一个比较特殊的值就是在\(i\in\mathbb{P}\)时有\(f(i)=-1\)。于是考虑PowerfulNumber筛,构造积性函数\(g\)使得对于\(i\in\mathbb{P}\)有\(g(p)=f(p)\)且\(g\)易......