首页 > 其他分享 >[题解] AtCoder Beginner Contest 308 A~G

[题解] AtCoder Beginner Contest 308 A~G

时间:2023-09-07 16:13:05浏览次数:38  
标签:308 Contest int 题解 mst cin ++ vector auto

AtCoder Beginner Contest 308 A~G

A. New Scheme

void Main() {
    vector<i64> a(8);
    for (auto &x : a) cin >> x;
    if (!is_sorted(a.begin(), a.end()) && !all_of(a.begin(), a.end(), [](auto &x) { return x % 25 != 0 || !(100 <= x && x <= 675); })) {
        cout << "No\n";
    } else {
        cout << "Yes\n";
    }
}

B. Default Price

void Main() {
    int n, m;
    cin >> n >> m;
    vector<string> a(n);
    for (auto &x : a) cin >> x;
    map<string,int> mp;
    vector<string> b(m);
    for (int i = 0; i < m; i ++) {
        cin >> b[i];
    }
    i64 ans = 0, t = 0;
    cin >> t;
    for (int i = 0; i < m; i ++) {
        cin >> mp[b[i]];
    }
    for (int i = 0; i < n; i ++) {
        if (!mp.count(a[i])) {
            ans += t;
        } else {
            ans += mp[a[i]];
        }
    }
    cout << ans << '\n';
}

C. Standings

至少我用 long double 居然没过……

void Main() {
    int n;
    cin >> n;
    vector<array<i64,3>> a(n + 1);
    for (int i = 1; i <= n; i ++) {
        i64 x, y;
        cin >> x >> y;
        auto g = gcd(x, y + x);
        a[i] = {x / g, (x + y) / g, i};
    }
    sort(a.begin() + 1, a.end(), [](const auto &a, const auto &b) {
        auto x = a[0] * b[1], y = a[1] * b[0];
        if (x == y) {
            return a[2] < b[2];
        } else {
            return x > y;
        }
    });
    for (int i = 1; i <= n; i ++) {
        cout << a[i][2] << " \n"[i == n];
    }
}

D. Snuke Maze

搜一下就可以,但是要注意的是,如果可以重复走到以前的路,那么代表这里有个循环,也其实是不需要走多走循环也可以到达,因此需要一个 vis 标记一下。

void Main() {
    int n, m;
    cin >> n >> m;

    vector a(n + 2, vector<char>(m + 2));
    map<char,char> nex {
        {'s', 'n'}, {'n', 'u'}, {'u', 'k'}, {'k', 'e'}, {'e', 's'}
    };

    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            char x;
            cin >> x;
            if (nex.count(x))
                a[i][j] = x;
        }
    }

    if (a[1][1] == 0) {
        cout << "No\n";
        return;
    }

    vector vis(n + 2, vector<bool>(m + 2));
    auto dfs = [&](auto &&dfs, int x, int y) -> void {
        if (x == n && y == m) {
            cout << "Yes\n";
            exit(0);
        }
        vis[x][y] = true;
        for (auto [nx, ny] : array<pair<int,int>,4>{pair{x + 1, y}, {x. 1, y}, {x, y + 1}, {x, y. 1}}) {
            if (!vis[nx][ny] && a[nx][ny] == nex[a[x][y]]) {
                dfs(dfs, nx, ny);
            }
        }
    };
    dfs(dfs, 1, 1);
    cout << "No\n";
}

E. MEX

显然是一个枚举一个点的套路题。

注意到,我们枚举的三个位置必须符合 MEX 这样的形式,那么我们可以枚举 E 的位置,这样问题就转化为枚举 E ,求前缀 M 和后缀 X 的组合有多少种,所以需要知道对于一个位置 E ,前缀有多少个 M ,后缀有多少个 X 。最后求遍 mex 算结果即可。

void Main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i ++) {
        cin >> a[i];
    }
    string s;
    cin >> s;

    map<pair<char,int>, vector<i64>> pre, rep;
    for (auto c : {'M', 'E', 'X'}) {
        for (auto i : {0, 1, 2}) {
            pre[{c, i}].assign(n + 2, 0);
            rep[{c, i}].assign(n + 2, 0);
        }
    }

    for (int i = 0; i < n; i ++) {
        pre[{s[i], a[i]}][i + 1] = rep[{s[i], a[i]}][i + 1] = 1;
    }

    for (auto c : {'M', 'E', 'X'}) {
        for (auto i : {0, 1, 2}) {
            auto x = pair{c, i};
            for (int i = 1; i <= n; i ++) {
                pre[x][i] += pre[x][i - 1];
            }
            for (int i = n; i >= 1; i --) {
                rep[x][i] += rep[x][i + 1];
            }
        }
    }


    i64 ans = 0;
    for (int i = 2; i <= n - 1; i ++) {
        if (s[i - 1] == 'E') {
            auto tag = pair{s[i - 1], a[i - 1]};
            for (int j = 0; j < 3; j ++) {
                for (int k = 0; k < 3; k ++) {
                    auto cnt = pre[{'M', j}][i] * rep[{'X', k}][i];
                    array tmp {k, j, a[i - 1]};
                    sort(tmp.begin(), tmp.end());
                    int mex = 0;
                    for (auto x : tmp) mex += mex == x;
                    ans += cnt * mex;
                }
            }
        }
    }
    cout << ans << '\n';
}

F. Vouchers

贪心。

我们希望最后的花费最少,那么对于每张折扣券,找一个目前还未被使用的、价格最接近使用界限的商品使用即可。同时我们需要注意的是,我们希望折扣力度最大,那么我们就需要先按折扣价格最多的来算,尽量让这张券用上,力度小的,如果能用就用了,没法用就算了。

template <typename T, typename Compare = std::greater<T>>
using BinaryHeap = std::priority_queue<T, std::vector<T>, Compare>;

void Main() {
    int n, m;
    cin >> n >> m;
    multiset<i64> st;
    i64 ans = 0;
    for (int i = 0; i < n; i ++) {
        int x;
        cin >> x;
        st.emplace(x);
        ans += x;
    }
    vector<pair<i64,i64>> b(m);
    for (int i = 0; i < m; i ++) {
        i64 x;
        cin >> x;
        b[i].second = x;
    }
    for (int i = 0; i < m; i ++) {
        i64 x;
        cin >> x;
        b[i].first = x;
    }
    sort(b.begin(), b.end());
    while (!b.empty()) {
        auto [d, l] = b.back();
        b.pop_back();
        auto it = st.lower_bound(l);
        if (it == st.end()) {
            continue;
        } else {
            ans -= d;
            st.extract(it);
        }
    }
    cout << ans << '\n';
}

G. Minimum Xor Pair Query

问目前的序列中任意两个数异或得到的最小异或和是多少。

有一个特殊的性质:对于一个序列来说,其任意两个数异或得到的最小值一定存在于其从小到大排序后相邻两项的异或和。如果注意到这个性质,那么就可以拿两个 multiset 做完这道题了。一个存序列,一个存结果,添加或删除的时候需要调整一下结果即可。

void Main() {
    int q;
    cin >> q;
    multiset<int> mst, ret;
    for (int i = 0; i < q; i ++) {
        int opt, x;
        cin >> opt;
        if (opt == 1) {
            cin >> x;
            auto pit = mst.lower_bound(x);
            if (pit != mst.end() && pit != mst.begin()) {
                ret.extract(*pit ^ *prev(pit));
            }
            auto it = mst.emplace(x);
            if (it != mst.begin()) {
                ret.emplace(*it ^ *prev(it));
            }
            if (next(it) != mst.end()) {
                ret.emplace(*it ^ *next(it));
            }
        } else if (opt == 2) {
            cin >> x;
            auto it = mst.lower_bound(x);
            if (it != mst.begin()) {
                ret.extract(*it ^ *prev(it));
            }
            if (next(it) != mst.end()) {
                ret.extract(*it ^ *next(it));
            }
            it = mst.erase(it);
            if (it != mst.end()) {
                if (it != mst.begin()) {
                    ret.emplace(*it ^ *prev(it));
                }
            }
        } else {
            cout << *ret.begin() << '\n';
        }
    }
}

标签:308,Contest,int,题解,mst,cin,++,vector,auto
From: https://www.cnblogs.com/FlandreScarlet/p/17685205.html

相关文章

  • CF1374E2 Reading Books(hard version) 题解
    CF1374E2ReadingBooks(hardversion)这道题是在CF1374E1ReadingBooks(easyversion)的基础上出的,而且仅仅增加了一个\(m\)的限制,下面的做法也是基于简单版的思路而想到的。建议先尝试简单版,然后尝试此题。题意简述:有\(n\)本书,每本书有一个阅读时间\(t_i\),和属性\(......
  • Eclipse里做JBPM工作流gpd.xml中文乱码问题解决
         刚开始接到是做一个简单的文档借阅流程,对于流程定义是采用eclipse中的jbpm插件,但存在一个问题是节点中文命名的在gpd.xml中全部为乱码或根本看不到任何东西。     但是网上有人说没关系,这只是eclipse本身存在的一个bug,在项目所在硬盘目录下打开该文件还是显示正常......
  • 题解 [NOIP2018 提高组] 赛道修建
    题目链接挺综合的一道题目。询问最小值最大,考虑二分最小值,二分上下界是\([最小边权,树的直径]\),但是为了方便我们直接设为\([1,5\times10^8]\)即可。考虑如何\(check\),可以采用类似树形\(dp\)的方式进行贪心。对于节点\(u\)的子树,\(u\)内部的点显然可以构成几条链,同......
  • 【PCL】使用kdtree时pop_t报错问题解决
    问题描述在使用kdtree时,遇到的报错,具体报错信息如下:提示找不到pop_t,点击错误信息会进入到dist.h文件中问题解决解决办法很简单,在这里简单总结一下进入dist.h文件中,将下面这行代码,应该是在源文件的503行:typedefunsignedlonglongpop_t;具体位置如下图所示:将这行代码......
  • FTP权限问题解析,553 Can't open that file: Permission denied
    FTP权限问题解析,553Can'topenthatfile:Permissiondenied FTP上传文件,提示553Can'topenthatfile:Permissiondenied原因:目录的所属组,所属用户属于root,导致FTP无法上传,修改组和所属用户为www即可chown-fRwww./*chgrp-fRwww./* ......
  • 9.6 CF1830 题解
    9.6CF1830题解A.CopilCopacDrawsTrees链接真弱智题不用讲B.TheBOSSCanCountPairs题意每组数据给你一个\(n\)和两个序列\(a,b\)。求有多少个数对\((i,j)\)满足\(1\lei<j\len\)且\(a_i\timesa_j=b_i+b_j\)。题解考虑\(a_i\timesa_j=b_i......
  • 【题解】CF2600DP 选练(23.9.5-23.9.6)
    低情商:感觉是比较套路的高情商:十分educational!!!CF258DLittleElephantandBrokenSorting题目描述:有一个\([1,n]\)的排列\(a\),会进行\(m\)次操作,操作为交换\((a_i,a_j)\)。每次操作都有\(50\%\)的概率进行。求进行\(m\)次操作以后的期望逆序对个数。\(n,m\le1......
  • 爱思创CSP第一轮模拟赛01易错题解析
    一.1.错误原因:不知道解析:正确答案B星型结构,类似于一颗星星,优点是节省材料,弊端是,如果源点计算机故障,那么网络就会瘫痪。环形结构,类似于一个环,环上有一些端点,每个端点对应着一台计算机,弊端是,如果在环上断了2条边,网络就会瘫痪网状结构,就是现在的因特网(Internet),类似于一张图,......
  • $9.6$ 短学期题解
    \(a\)inta[N];voidsolve(){intn=read();for(inti=1;i<=n;i++){a[i]=read();}sort(a+1,a+1+n);intans=0;for(inti=1;i<=min(5,n);i++){if(a[i]<=300)ans++;}puts(ans>=5?"PentaKill&qu......
  • Iksevi 题解
    题目大意\(n\)次询问,每次给定一个点\((x,y),x\ge0,y\ge0\),问有多少种对角线长为偶数的正方形使得在用该正方形正密铺第一象限的情况下该点位于正方形顶点上。正密铺第一象限指将第一个正方形的角与\(x\)轴和\(y\)轴接触。此后的正方形都与至少一个已放置的正方形有一......