Educational Codeforces Round 69 (Rated for Div. 2)


A. DIY Wooden Ladder

题意:\(n\)个数里选\(k + 2\)个数,使得最大的两个数都大于\(k\)。求最大的\(k\)

显然最从大的数选更优。那么最大两个数就固定了,给\(a\)排序后,答案就是\(\min(a_{n-1} - 1, n - 2)\)

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::ranges::sort(a);
    std::cout << std::min(a[n - 2] - 1, n - 2) << "\n";
}

B. Pillars

题意:\(n\)个柱子开始有第\(a_i\)个盘子在上面。如果一个柱子上只有一个盘中,那么可以移动到两边的柱子,只要满足这个柱子没有盘子或者这个柱子的盘子大于当前盘子。判断能不能都移动到一个柱子上。

如果\(i\)要到\(i + 1\),那么中间不能有小于它们的数。可以用线段树或者ST表维护区间最小值。但思考发现,满足这个条件的序列一定是一个先递增然后递减的序列。判断是不是满足这个条件就行。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    int l = 0, r = n - 1;
    while (l + 1 < n && a[l + 1] > a[l]) {
    	++ l;
    }

    while (r - 1 >= 0 && a[r - 1] > a[r]) {
    	-- r;
    }

    if (l == r) {
    	std::cout << "YES\n";
    } else {
    	std::cout << "NO\n";
    }
}

C. Array Splitting

题意:一个递增的数组,分成\(k\)段,每段的值为最大值减最小值。要求和最小。

假设\(k\)段是\([a_1, a_{p_1}], [a_{p_1 + 1}, a_{p_2}], ... , [a_{p_k-1 + 1}, a_n]\)。因为数组是排序的,那么只有每段的端点产生贡献,那么就是\(a_n - a_1 + \sum_{i=1}^{k-1} a_{p_1} - a_{p_1 + 1}\)。我们希望后一项最小,那么可以把所有\(a_i - a_{i+1}\)排序,取前\(k-1\)个最小的。

点击查看代码
void solve() {
    int n, k;
    std::cin >> n >> k;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    i64 ans = a[n - 1] - a[0];
    std::vector<int> b;
    for (int i = 0; i + 1 < n; ++ i) {
    	b.push_back(a[i] - a[i + 1]);
    }

    std::ranges::sort(b);
    for (int i = 0; i + 1 < k; ++ i) {
    	ans += b[i];
    }

    std::cout << ans << "\n";
}

D. Yet Another Subarray Problem

题意:选一个子数组\(a_l, .. a_r\)。代价为\((\sum_{i=l}^{r} a_i) - k\times \lceil \frac{r-l+1}{m} \rceil\)。求最大代价。

固定左端点\(i\),发现右端点\(j\)\(i\% m = j\% m\)时会多减一个\(k\)。同时用前缀和使得\(\sum_{i=l}^{r} a_i = sum_r - sum_{l-1}\)。那么把元素分成\(m\)组,然后一个一个数加入,那么因为子数组是连续的,那么所有\(m\)组都要加上它,同时和它取模\(m\)相同的组要多减一个\(k\),做一个类似最大子段和的东西就行。

点击查看代码
void solve() {
    i64 n, m, k;
    std::cin >> n >> m >> k;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    const i64 inf = 1e18;
    std::vector<i64> sum(m, -inf);
    i64 ans = 0;
    for (int i = 0; i < n; ++ i) {
    	for (int j = 0; j < m; ++ j) {
    		sum[j] += a[i];
    	}

    	sum[i % m] = std::max(sum[i % m], a[i]) - k;
    	for (int j = 0; j < m; ++ j) {
    		ans = std::max(ans, sum[j]);
    	}
    }

    std::cout << ans << "\n";
}
posted @ 2025-04-27 16:49  maburb  阅读(19)  评论(0)    收藏  举报