Atcoder Beginner Contest 306 A~E题解

这次感觉比之前简单一些

A - Echo

题目
给一个字符串s,重复每个字符两次

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;

void solve()
{
    int n;
    string s;
    cin >> n >> s;
    for (auto c : s) cout << c << c;
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

B - Base 2

题目
给一个01输入,二进制转十进制

#include <bits/stdc++.h>
#define int unsigned long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;

void solve()
{
    int ans = 0;
    uf (i, 0, 63) 
    {
        int t;
        cin >> t;
        if (t) ans += 1ull << i;
    }
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

C - Centers

题目
给 3n 长的序列, 1~n 的元素会重复三次,按照出现在中间的元素位置升序输出每个元素

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;
const int N  = 1e5 + 5;
int a[N * 3];
bool st[N];
void solve()
{
    int n;
    cin >> n;
    unordered_map<int, int> mp;
    uf (i, 1, 3 * n) 
    {
        cin >> a[i];
        if (st[a[i]]) 
        {
            mp[a[i]] = i;
            st[a[i]] = 0;
        }
        else st[a[i]] = 1;
    }
    vector<pii> p (all(mp));
    sort(all(p), [](pii a, pii b)
    {
        return a.y < b.y;
    });
    for (auto pair : p) cout << pair.x << " ";
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

D - Poisonous Full-Course

题目
由n种菜,每种菜有毒或者解毒,都有一个味道值;初始健康,吃一个有毒的菜会不舒服,如果连续吃两个有毒的菜就会die,如果吃了一个有毒的菜再吃一个解毒的菜就能恢复健康。对于每一种菜可以选择吃或者不吃,求吃下的菜最大的味道值。

  • dp,两种状态,dp[i][0 / 1] :当前吃到第 i 种菜且为 0/1 状态的最大滋味值(0为健康,1为不舒服)
  • 状态转移看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;
const int N = 3e5 + 5;
vector<pii> a(N);
void solve()
{
    int n;
    cin >> n;
    uf (i, 1, n) cin >> a[i].x >> a[i].y;
    vector<vi> dp(N, vi(2, 0));
    uf (i, 1, n)
    {
        if (a[i].x == 1) //有毒
        {
            dp[i][0] = dp[i - 1][0]; //跳过
            dp[i][1] = max(dp[i - 1][0] + a[i].y, dp[i - 1][1]); //在健康状态下可以吃,不舒服状态跳过
        } 
        else
        {
            dp[i][0] = max({dp[i - 1][0], dp[i - 1][0] + a[i].y, dp[i - 1][1] + a[i].y}); //健康状态不吃、健康状态下吃、不舒服状态下吃
            dp[i][1]  = dp[i - 1][1]; //不舒服状态下选择不吃
        }
    }
    cout << max(dp[n][0], dp[n][1]) << endl;
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

E - Best Performances

题目
初始全为0的序列,q次修改, 每次修改某个位置x上的数为 y, 然后输出最大的 k 个数的和

  • 用两个堆来维护,heap 维护 最大的 k 个数, other 维护没有在 heap 里面的数
  • 当修改x位置上的数为y时就可以判断:
    • x不在 heap 中:判断能不能加入 heap
    • x 在 heap 中:判断能不能继续在 heap
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define x first
#define y second
#define INF 0x3f3f3f3f
#define vi vector<int>
#define pii pair<int, int>
#define mset(x, v) memset(x, v, sizeof x)
#define all(x) ((x).begin()), ((x).end())
#define uf(i, j, k) for (int i = j; i <= k; i ++)
#define df(i, j, k) for (int i = j; i >= k; i --)

using namespace std;
const int N = 5e5 + 5;
int n, k, q;
vi a(N, 0);

void solve()
{
    cin >> n >> k >> q;
    set<pii> heap, other;
    unordered_set<int> st;
    int sum = 0;
    uf (i, 1, k) heap.insert({0, i}), st.insert(i);
    uf (i, k + 1, n) other.insert({0, i});
    int x, y;
    while (q --)
    {
        cin >> x >> y;
        int pre = a[x];
        a[x] = y;
        auto mn = (*heap.begin()).x, pos = (*heap.begin()).y;
        if (st.count(x)) //存在于堆中
        {   
            int mx = INT_MIN, p = 0;
            if (other.size())  mx = (*other.rbegin()).x, p = (*other.rbegin()).y;
            if (y >= mx) //大于最小值没有影响
            {
                heap.erase({pre, x});
                heap.insert({y, x});
                sum = sum + y - pre;
            }
            else
            {
                other.erase({mx, p});
                other.insert({y, x});
                heap.insert({mx, p});
                heap.erase({pre, x});
                st.insert(p);
                st.erase(x);
                sum = sum - pre + mx;
            }
        } 
        else //不存在于堆中
        {
            if (y > mn)  //只有大于堆的最小值才能加入
            {
                heap.erase(heap.begin());
                heap.insert({y, x}); //插入到堆中
                other.erase({pre, x}); //从其他删除
                other.insert({mn, pos}); //插入到其他
                st.erase(pos); //从堆里面删除 
                st.insert(x);
                sum = sum + y - mn;
            } 
            else 
            {
                other.erase({pre, x});
                other.insert({y, x});
            }
        }
        cout << sum << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

自己和镜中对抗
赢不回诗和远方
任世故欲盖弥彰
他奋力撕掉伪装
转身间对视过往
道一句 怪人生无常

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值