Educational Codeforces Round 158 A~D(div2-思维/构造/贪心 补C~D)

链接: https://codeforces.com/contest/1901

A. Line Trip(思维)

题意:

给定一长度为 x x x 的数轴,和 n n n 个加油站,问开车支持来回所需的最小油箱容量。

思路:

维护一个最大值,代表每次刚好到加油站的最小容量,请注意最后的加油站到终点可能有段距离。

代码:

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
ll n, k, ans = 0;
void solve()
{
    cin >> n >> k;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    ans = a[1];
    for (int i = 2; i <= n; i++) {
        ans = max(ans, a[i] - a[i - 1]);
    }
    ans = max((k - a[n]) * 2, ans);
    cout << ans << endl;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	// cout.tie(0);
	ll _;cin>>_;
	while(_--)
		solve();
	return 0;
}

B. Chip and Ribbon(思维/贪心)

题意:

给定一条有初始值的丝带和初始位置任意选择的细胞,你可以进行两个操作:1、将细胞位置从 a i a_i ai 移动到 a i + 1 a_{i+1} ai+1 。2、将细胞传送到任意 a i a_i ai 位置。每次移动会使得 a i a_i ai 位置上的初始值 − 1 -1 1 问让初始值全变为 0 0 0 的最小传送数。

思路:

我们要尽可能用移动的操作去消除初始值,所以肯定是从左边开始考虑最好,每碰到一个大于上一个的值,肯定要多传送 a i − a i − 1 a_i-a_{i-1} aiai1 遍。具体看代码,要注意一开始放置不消耗传送次数。

代码:

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
ll n, ans = 0;
void solve()
{
    cin >> n;
    vector<ll> c(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    ans = c[1] - 1;
    for (int i = 2; i <= n; i++) {
        if (c[i] > c[i - 1] && c[i] != 0) {
            ans += c[i] - c[i - 1];
        }
    }
    cout << ans << endl;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	// cout.tie(0);
	ll _;cin>>_;
	while(_--)
		solve();
	return 0;
}

C. Add, Divide and Floor(思维/构造/贪心)

题意:

给定长度为 n n n 的数组 a a a ,每次选定一个 x x x 让得每一个 a i a_i ai 变成 f l o o r ( ( a i + x ) / 2 ) , f l o o r floor((a_i+x)/2),floor floor((ai+x)/2)floor 表示向下取整,若干次操作后使得数组 a a a 内所有值相等。问该操作次数的最小值是多少,如果操作次数大于 n n n 则不用输出每次选择的 x x x ,否则需要。

思路:

我们发现这个操作次数最小会让最大值最快接近最小值,当这两个值相等,其他值也会随之相等。所以只需要维护最大值 a m a x a_{max} amax 和最小值 a m i n a_{min} amin 。容易发现有两种情况:1、 a m a x 、 a m i n a_{max}、a_{min} amaxamin 都会更新,最后相等。2、 a m a x a_{max} amax 更新, a m i n a_{min} amin 不变,最后相等。在这里我选择了 2 2 2 。所以每次选定的 x x x 都是 a m i n a_{min} amin

代码:

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
ll n, ans = 0;
void solve()
{
    cin >> n;
    ll a[n + 1];
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    if (n == 1) {
        cout << 0 << endl;
        return;
    }
    sort(a + 1, a + 1 + n);
    ans = 0;
    vector<ll> ans_a;
    while (a[1] != a[n]) {
        a[n] = (a[n] + a[1]) / 2;
        ans_a.push_back(a[1]);
    }
    ans = (ll)ans_a.size();
    cout << ans << endl;
    if (ans > n)
        return;
    for (int i = 1; i <= ans; i++) {
        cout << ans_a[i - 1] << " \n"[i == ans];
    }
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	// cout.tie(0);
	ll _;cin>>_;
	while(_--)
		solve();
	return 0;
}

D. Yet Another Monster Fight(思维/贪心/DP/前缀和/二分答案)

题意:

给定 n n n 只怪,你可以任意选定一个怪开始攻击,攻击会连带触发,攻击伤害会向相邻的怪随机选择,攻击伤害每次递减 1 1 1 。问这个攻击伤害 x x x 最小为多少,可以在随机情况下使得怪全部寄。

思路(前缀和):

随机情况说明要往最坏情况去考虑,假设我们选定 k k k 位置开始,对于每个位置 i i i ,最坏情况都是先干掉相邻的其他怪再轮到自己,所以当 i ≤ k , x − ( n − i + 1 ) + 1 ≥ a i i≤k,x-(n-i+1)+1≥a_i ikx(ni+1)+1ai x ≥ a i − i + n x≥a_i-i+n xaii+n ,当 i ≥ k , x − i + 1 ≥ a i i≥k,x-i+1≥a_i ikxi+1ai x ≥ a i + i + 1 x≥a_i+i+1 xai+i+1 。再用一个前缀和数组和后缀和数组去维护即可。

代码(前缀和):

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll INF_ = 0x3f3f3f3f3f3f3f3f;
ll n, ans = 0;
ll a[N], pre[N], suf[N];
void solve()
{
    cin >> n;
    ans = INF_;
    pre[0] = suf[n + 1] = 0;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        pre[i] = max(pre[i - 1], a[i] - i + n);
    }
    for (int i = n; i >= 1; i--) {
        suf[i] = max(suf[i + 1], a[i] + i - 1);
        ans = min(ans, max({ pre[i - 1], suf[i + 1], a[i] }));
    }
    cout << ans << endl;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	// cout.tie(0);
	// ll _;cin>>_;
	// while(_--)
		solve();
	return 0;
}

E. Compressed Tree(树形DP)

题意:

思路:

代码:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Educational Codeforces Round 146 (Rated for Div. 2)比赛中,有关于一个节点数量为n的问题。根据引用的结论,无论节点数量是多少,都可以将其分成若干个大小为2或3的区间使其错排,从而减少花费。根据引用的推导,我们可以通过组合数和差量来表示剩余的花费。而引用进一步推广了这个结论,可以使得任意长度的一段错排花费代价为边权和的两倍,并且通过贪心算法使得更多的边不被使用。以此来解决与节点数量相关的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Educational Codeforces Round 146 (Rated for Div. 2)(B,E详解)](https://blog.csdn.net/TT6899911/article/details/130044099)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Educational Codeforces Round 83 (Rated for Div. 2) D](https://download.csdn.net/download/weixin_38562130/14878888)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值