Final_The_2nd_Universal_Cup_Stage_7_Two_Capital

The 2nd Universal Cup. Stage 7: Two Capital

题目 B: Bins and Balls

题目链接

代码实现:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 2e5 + 10;

void solved() {
    int n, k;
    cin >> n >> k;
    vector<int> arr;
    for (int i = 1; i <= n; i++) {
        int v;
        cin >> v;
        arr.push_back(v);
    }
    int l = 0, r = 2e14 + 10;
    while (l <= r) {
        int mid = (l + r) >> 1;
        int pre = 0;
        for (int i = 0; i < n; i++) {
            if (arr[i] >= mid) {
                pre += mid;
            } else {
                pre += arr[i];
            }
        }
        if (pre / k >= mid) {
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    cout << r << endl;
}

signed main() {
    close;
    solved();
    return 0;
}

题目分析:

这是一道思维题目,可以通过二分答案解决。答案的最小值为0,最大值则可以推导为 (2e14) 左右。要判断当前中间值是否符合要求,需要遍历数组,计算每个数值对中间值的贡献(取最小值)。通过二分法逐步逼近最终答案。


题目 G: Lake

题目链接

代码实现:

#include <bits/stdc++.h>
using namespace std;
#define int long long int

signed main() {
    int n, m;
    cin >> n >> m;
    int ans = 0;
    while (n > 0 || m > 0) {
        if (n >= 3 && m >= 3) {
            n -= 3;
            m -= 3;
            if (n > m) {
                --n;
            } else {
                --m;
            }
        } else if (n >= 3) {
            m = 0;
            n -= 4;
        } else if (m >= 3) {
            m -= 4;
            n = 0;
        } else {
            m = 0;
            n = 0;
        }
        ++ans;
    }
    cout << 2*ans-1 << endl;
    return 0;
}

题目分析:

这道题的核心是模拟,判断每次如何调整两个变量 n 和 m。每次根据两者的值作出决策,逐步减少它们的值,最终求得答案。


题目 J:Range Sets

代码实现:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 1e5 + 10;
int tot, rt;
int n, q;
struct SMT
{
    int ls, rs;
    int v;
} seg[N * 40];
struct Node
{
    int l, r;
    mutable int val;
    Node(int _l, int _r, int _val) : l(_l), r(_r), val(_val) {}
    bool operator<(const Node &other) const
    {
        return l < other.l;
    }
};
typedef set<Node>::iterator S_IT;
inline void modify(int &id, int l, int r, int ql, int qr, int v)
{
    if (!id)
    {
        id = ++tot;
    }
    if (ql <= l && r <= qr)
    {
        seg[id].v += v;
        return;
    }
    int mid = (l + r) >> 1;
    if (ql <= mid)
    {
        modify(seg[id].ls, l, mid, ql, qr, v);
    }
    if (qr > mid)
    {
        modify(seg[id].rs, mid + 1, r, ql, qr, v);
    }
}

inline int query(int id, int l, int r, int pos)
{
    if (!id)
        return 0;
    int mid = (l + r) >> 1;
    if (pos <= mid)
    {
        return query(seg[id].ls, l, mid, pos) + seg[id].v;
    }
    else
    {
        return query(seg[id].rs, mid + 1, r, pos) + seg[id].v;
    }
}
struct ODT
{
    set<Node> s;
    S_IT split(int pos)
    {
        auto it = s.lower_bound(Node(pos, 0, 0));
        if (it != s.end() && it->l == pos)
            return it;
        if (it == s.begin())
            return s.end();
        --it;
        int l = it->l, r = it->r;
        int v = it->val;
        s.erase(it);
        s.insert(Node(l, pos - 1, v));
        return s.insert(Node(pos, r, v)).first;
    }
    inline void assign(int L, int R, int v)
    {
        S_IT itr = split(R + 1), itl = split(L);
        for (S_IT it = itl; it != s.end() && it->l <= R;)
        {
            if (it->val != v)
            {
                modify(rt, 1, n, it->l, it->r, v - it->val);
            }
            it = s.erase(it);
        }
        s.insert(Node(L, R, v));
    }
} tr[N * 40];
void solved()
{
    cin >> n >> q;
    unordered_map<int, int> mp;
    while (q--)
    {
        char op;
        cin >> op;
        if (op == '?')
        {
            int pos;
            cin >> pos;
            cout << query(rt, 1, n, pos) << endl;
        }
        else if (op == '-')
        {
            int l, r, x;
            cin >> l >> r >> x;
            if (!mp.count(x))
            {
                mp[x] = ++tot;
                tr[mp[x]].s.insert(Node(1, n, 0));
            }
            tr[mp[x]].assign(l, r, 0);
        }
        else
        {
            int l, r, x;
            cin >> l >> r >> x;
            if (!mp.count(x))
            {
                mp[x] = ++tot;
                tr[mp[x]].s.insert(Node(1, n, 0));
            }
            tr[mp[x]].assign(l, r, 1);
        }
    }
}
signed main()
{
    close;
    solved();
    return 0;
}

题目分析:

这是一道数据结构题目,涉及动态开点线段树的操作。通过使用线段树,我们可以高效处理区间修改和单点查询操作。这种数据结构可以用于优化时间复杂度,在面对较大的数据范围时尤为实用。后续会更新更详细的讲解。


题目 K: Integer Half-Sum

代码实现:

#include <bits/stdc++.h>
using namespace std;
#define int long long int
#define close ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

signed main() {
    close;
    int l, r;
    cin >> l >> r;
    if (l == r)
        cout << l << endl;
    else if (l == r - 1)
        cout << -1 << endl;
    else
        cout << r - 1 << endl;
    return 0;
}

题目分析:

考虑 (l) 和 (r) 的情况,如果两个数相邻,那么一定是一个奇数,一个偶数,结果为 -1;如果两个数相等 (l == r),则答案为 (l);如果这两个数中间至少隔了一个数,则可以继续操作(三个一组)直到得到答案。


题目 H: Forbidden Set

题目链接

代码实现:

#include <bits/stdc++.h>
using namespace std;
#define int long long int
#define close ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 5e6;
vector<int> pri;
bool not_prime[N];

void pre(int n) { 
    for (int i = 2; i <= n; ++i) { 
        if (!not_prime[i]) 
            pri.push_back(i); 
        for (int pri_j : pri) { 
            if (i * pri_j > n) 
                break; 
            not_prime[i * pri_j] = true; 
            if (i % pri_j == 0) 
                break; 
        } 
    } 
}

signed main() {
    close;
    int ans = -1;
    int n;
    cin >> n;
    pre(2000);
    vector<bool> s(11);
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        s[x] = true;
    }
    for (auto i : pri) {
        bool f = false;
        int t = i;
        while (t) {
            int a = t % 10;
            t /= 10;
            if (s[a]) {
                f = true;
                break;
            }
        }
        if (!f) {
            ans = i;
            break;
        }
    }
    cout << ans << endl;
    return 0;
}

题目分析:

这道题通过对素数的处理,寻找符合条件的数。我们预处理 2000 以内的素数,并进行枚举,检查是否存在禁止的数字。通过这种方式,我们可以有效地找到符合条件的最小素数。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值