Educational Codeforces Round 172 Solution

A. Greedy Monocarp

题目大意

有N个箱子,第i个箱子里有Ai个硬币,有一个人会从多到少拿这些箱子。

现在你可以给一个箱子加若干硬币,请你使这个人可以拿到刚好K个硬币时停下拿箱子,要求加入的硬币数量尽量少。

解题思路

排个序,然后从大到小加,加到刚好不能再多加一个箱子为止,结果就是K-sum。

void solve()
{
    int n, k;
    cin >> n >> k;
    vi v(n);
    fore(i, v) cin >> i;
    sort(all(v));
    reverse(all(v));

    int sum = 0;
    rep(i, n) {
        sum += v[i];
        if (sum >= k) break;
        if (i != n - 1)
            if (sum < k && sum + v[i + 1] > k) {
                cout << k - sum << endl;
                return;
            }
    }
    cout << k - sum << endl;
}


B. Game with Colored Marbles

题目大意

两个人玩游戏,桌子上有N个不同颜色的弹珠,他们可以轮流选择弹珠拿走,最后拿完的时候记分,积分规则如下:

  • 有一个不同颜色的弹珠加一分
  • 完全拿完了一种颜色的弹珠加一分

两个人都采取最佳策略,问Alice最后的分数。

解题思路

对于单个的弹珠两个人肯定是轮流拿,剩下的弹珠Alice都能抢到一个。

int cnt[1005];
void solve()
{
    int n;
    cin >> n;

    vi v(n);
    memset(cnt, 0, sizeof(cnt));
    fore(i, v) {
        cin >> i;
        cnt[i]++;
    }
    int cnt1 = 0, cnt2 = 0;
    repo(i, 1000) {
        if (cnt[i] == 1) cnt1++;
        else if (cnt[i] != 0) cnt2++;
    }
    int ans = (cnt1 + 1) / 2 * 2 + cnt2;
    cout << ans << endl;
}

C. Competitive Fishing

题目大意

有一个序列,0表示Alice,1表示Bob,你可以把整个序列分成m段,对于第一段的积分为0,第二段积分为1,第三段积分为3...,两个人分别根据01在哪个段内加分。

现在Bob想领先Alice至少k分,问最少要分多少段(分段方式自选)

解题思路

考虑在某个位置划一刀带来的贡献,贡献就是后缀所有的位置的积分都会+1,那么Bob领先的差值就会增加后缀1的个数减去后缀0的个数。

那么对于每个位置都计算一下后缀1的个数减去0的个数,然后排个序算最少要划几刀就可以了。

int cnt[1005];
void solve()
{
    int n;
    cin >> n;

    vi v(n);
    memset(cnt, 0, sizeof(cnt));
    fore(i, v) {
        cin >> i;
        cnt[i]++;
    }
    int cnt1 = 0, cnt2 = 0;
    repo(i, 1000) {
        if (cnt[i] == 1) cnt1++;
        else if (cnt[i] != 0) cnt2++;
    }
    int ans = (cnt1 + 1) / 2 * 2 + cnt2;
    cout << ans << endl;
}

D. Recommendations

题目大意

有N个区间,一个区间如果完全包含另一个区间,那么就被称作是这个区间的predictor,求每个区间的所有predictor的相同覆盖段长度。

解题思路

显然相同覆盖段长度是这些predictor的最小的R-最大的L,那么就是一个二维数点,求以LR为XY轴的二维平面内,左上角的区域中最小的R和最大的L。

代码从X轴扫的,其实扫Y轴更方便。

const int m = 1e9 + 2;

int n, s[200005];

struct su {
    int x, y, id;
    bool operator<(const su& temp)const {
        if (x == temp.x) return y > temp.y;
        return x < temp.x;
    }
}a[200005];
int ans[200005];

void add(int x, int v) {
    for (;x <= n;x += x & -x) s[x] = max(s[x], v);
}

int ask(int x) {
    int res = 0;
    for (;x;x -= x & -x) res = max(s[x], res);
    return res;
}

void solve()
{
    cin >> n;
    set<int> q;
    vector<int> f;
    unordered_map<int, int> mp;
    for (int i = 1;i <= n;++i) {
        int x, y;
        cin >> x >> y;
        a[i].x = x;
        a[i].y = y;
        a[i].id = i;
        f.push_back(a[i].y);
        s[i] = 0;
    }
    sort(all(f));
    reverse(all(f));
    unique(all(f));
    for (int i = 0;i < f.size();++i) {
        if (i > 0 && (f[i] > f[i - 1])) break;
        mp[f[i]] = i + 1;
    }
    sort(a + 1, a + n + 1);
    repo(i, n) {
        if (i > 1) {
            q.insert(a[i - 1].y);
            add(mp[a[i - 1].y], a[i - 1].x);
        }
        if ((i > 1 && a[i].x == a[i - 1].x && a[i].y == a[i - 1].y) || (i < n && a[i].x == a[i + 1].x && a[i].y == a[i + 1].y)) {
            ans[a[i].id] = 0;
            continue;
        }
        auto xx = q.lower_bound(a[i].y);
        if (xx == q.end()) {
            ans[a[i].id] = 0;
            continue;
        }
        int y = ask(mp[a[i].y]);
        if (y == 0 || (*xx) < y) {
            ans[a[i].id] = 0;
            continue;
        }
        ans[a[i].id] = (*xx) - y - (a[i].y - a[i].x);

    }
    repo(i, n) {
        cout << ans[i] << "\n";
    }
}
posted @ 2024-12-03 00:50  ~清渠~  阅读(101)  评论(0编辑  收藏  举报