EPIC Institute of Technology Round Summer 2024 (Div. 1 + Div. 2) 题解(A~E)

A. Upload More RAM

Problem

你每秒都可以上传0GB或1GB的内存,但是每 k k k 秒最多上传1GB的内存。

问将 n n n GB的内存全部上传需要的最短时间。

数据范围: 1 ≤ n , k ≤ 100 1 \leq n,k \leq 100 1n,k100

Solution

最优的方案是第一秒的时候上传1GB,之后每 k k k 秒上传1GB。答案即为 ( n − 1 ) × k + 1 (n-1)\times k+1 (n1)×k+1

时间复杂度: O ( 1 ) O(1) O(1)

Code

	void solve()
	{
	    cin >> n >> k;
	    printf("%d\n", (n - 1) * k + 1);
	}

B. K-Sort

Problem

给定一个数组 { a } i = 1 n \{a\}_{i=1}^n {a}i=1n,每次可以花费 k + 1 k+1 k+1 枚硬币,从数组中选取 k k k 个元素,并执行 a i = a i + 1 a_i=a_i+1 ai=ai+1

问最少需要多少枚硬币,使得数组 { a } i = 1 n \{a\}_{i=1}^n {a}i=1n 是非递减。

数据范围: 1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 1\leq n \leq 10^5,1\leq a_i \leq 10^9 1n105,1ai109

Solution

假设数组 { b } i = 1 n \{b\}_{i=1}^n {b}i=1n 是得到的非递减数组,那么 b i b_i bi就是原数组前缀中最大的元素,可以通过 b i = m a x ( b i − 1 , a i ) b_i=max(b_{i-1},a_i) bi=max(bi1,ai) 得到。那么每个位置需要执行的操作次数为 d i = b i − a i d_i=b_i-a_i di=biai,将其记为数组 { d } i = 1 n \{d\}_{i=1}^n {d}i=1n,并对其进行从小到大的排序。

答案即为 a n s = ∑ ( d i − d i − 1 ) × ( n − i + 1 ) ans=\sum (d_i-d_{i-1})\times (n-i+1) ans=(didi1)×(ni+1),其中 d i − d i − 1 d_i-d_{i-1} didi1为需要重复的次数, n − i + 1 n-i+1 ni+1为每次操作需要的硬币。

时间复杂度: O ( n   l o g   n ) O(n\ log\ n) O(n log n)

Code

void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    int ma = a[1];
    vector<int> b;
    b.push_back(0);
    for (int i = 2; i <= n; i++)
    {
        ma = max(ma, a[i]);
        b.push_back(ma - a[i]);
    }
    sort(b.begin(), b.end());
    ll ans = 0;
    for (int i = 1; i < n; i++)
    {
        ans += (ll)(b[i] - b[i - 1]) * (n - i + 1);
    }
    printf("%lld\n", ans);
}

C. Basil’s Garden

Problem

给定一个数组 { h } i = 1 n \{h\}_{i=1}^n {h}i=1n,每秒钟,如果 i = n i=n i=n 或者 h i > h i + 1 h_i > h_{i+1} hi>hi+1,那么执行 h i = m a x ( 0 , h i − 1 ) h_i=max(0,h_i-1) hi=max(0,hi1)

问几秒钟后, h i = 0   ( 1 ≤ i ≤ n ) h_i=0\ (1\leq i\leq n) hi=0 (1in) 的情形第一次出现。

数据范围: 1 ≤ n ≤ 1 0 5 , 1 ≤ h i ≤ 1 0 9 1\leq n \leq 10^5,1\leq h_i \leq 10^9 1n105,1hi109

Solution

记该数组从 h i , ⋯   , h n h_i,\cdots, h_n hi,,hn 全部变为零需要的时间为 a i a_i ai

如果 h i − 1 ≤ a i h_{i-1}\leq a_i hi1ai,那么存在某一时刻,使得 h i − 1 = h i h_{i-1}=h_i hi1=hi,当经过 a i a_i ai 秒后,原数组 h i − 1 , h i , ⋯ h n h_{i-1},h_i,\cdots h_n hi1,hi,hn 变为 1 , 0 , ⋯   , 0 1,0,\cdots,0 1,0,,0,此时 a i − 1 = a i + 1 a_{i-1}=a_i+1 ai1=ai+1

如果 h i − 1 > a i h_{i-1}>a_i hi1>ai,经过 a i a_i ai秒后,原数组 h i − 1 , h i , ⋯ h n h_{i-1},h_i,\cdots h_n hi1,hi,hn 变为 h i − 1 − a i , 0 , ⋯   , 0 h_{i-1}-a_i,0,\cdots,0 hi1ai,0,,0,此时 a i − 1 = h i − 1 a_{i-1}=h_{i-1} ai1=hi1

整理后可以得到 a i − 1 = m a x ( a i + 1 , h i − 1 ) a_{i-1}=max(a_i+1,h_{i-1}) ai1=max(ai+1,hi1)

时间复杂度: O ( n ) O(n) O(n)

Code

void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    ll ans = 0;
    for (int i = n; i >= 1; i--)
    {
        if (a[i] <= ans)
        {
            ans++;
        }
        else
        {
            ans = a[i];
        }
    }
    printf("%lld\n", ans);
}

D. World is Mine

Problem

给定一个数组 { A } i = 1 n \{A\}_{i=1}^n {A}i=1n,Alice和Bob轮流取走其中的元素,Alice先取,如果当前玩家不能取任何元素,那么游戏结束。

Alice每次取走的元素必须严格大于Alice上一次取走的元素,而Bob可以从剩下的元素中任选一个。

x x x为Alice取走的个数,Alice希望 x x x越大越好,Bob希望 x x x越小越好。问最后 x x x为多少,如果两人都采取最优策略。

数据范围: 1 ≤ n ≤ 5000 , 1 ≤ a i ≤ n 1\leq n \leq 5000,1\leq a_i \leq n 1n5000,1ain

Solution

a i a_i ai 表示第 i i i大的值出现的次数。对于Alice来说,最佳的策略显然就是从小到大的取,而对Bob来说,就是在满足条件的情况下使得更多的 a k a_k ak变为0。

f i , j f_{i,j} fi,j 表示Bob在前 i i i 大的值中取走 j j j 个元素能使 a k = 0 a_k=0 ak=0的最大个数。状态初值设为 − ∞ -\infty f 0 , 0 = 0 f_{0,0}=0 f0,0=0

状态转移过程:

  • f i , j = m a x ( f i , j , f i − 1 , j ) f_{i,j}=max(f_{i,j},f_{i-1,j}) fi,j=max(fi,j,fi1,j),这是不将 a i a_i ai改为0的情形。
  • i − f i − 1 , j − a i − 1 ≥ j i-f_{i-1,j-a_i}-1\geq j ifi1,jai1j时, f i , j = m a x ( f i , j , f i − 1 , j − a i + 1 ) f_{i,j}=max(f_{i,j},f_{i-1,j-a_i}+1) fi,j=max(fi,j,fi1,jai+1)。这是将 a i a_i ai改为0的情形,需要满足Alice拿走的个数( i − f i − 1 , j − a i − 1 i-f_{i-1,j-a_i}-1 ifi1,jai1 )大于等于Bob拿走的个数( j j j )。

最后的答案为 m − m a x ( f m , k ) m-max(f_{m,k}) mmax(fm,k),其中 m m m表示数组 { A } i = 1 n \{A\}_{i=1}^n {A}i=1n中不同元素的个数。

时间复杂度: O ( n 2 ) O(n^2) O(n2)

Code

void solve()
{
    cin >> n;
    for (int i = 0; i <= n; i++)
    {
        cnt[i] = 0;
        for (int j = 0; j <= n; j++)
        {
            f[i][j] = -1e9;
        }
    }
    for (int i = 1; i <= n; i++)
    {
        int a;
        cin >> a;
        cnt[a]++;
    }
    vector<int> a;
    a.push_back(0);
    for (int i = 1; i <= n; i++)
    {
        if (cnt[i])
        {
            a.push_back(cnt[i]);
        }
    }
    int m = a.size() - 1;
    f[0][0] = 0;
    for (int i = 1; i <= m; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            f[i][j] = f[i - 1][j];
            if (j >= a[i] && i - j >= f[i - 1][j - a[i]] + 1)
            {
                f[i][j] = max(f[i][j], f[i - 1][j - a[i]] + 1);
            }
            // printf("%d ", f[i][j]);
        }
        // printf("\n");
    }
    int ans = 0;
    for (int i = 1; i <= m; i++)
    {
        ans = max(ans, f[m][i]);
    }
    printf("%d\n", m - ans);
}

E. Wonderful Tree!

Problem

给定一棵 n n n个顶点的树,根为顶点1,同时每个顶点都有值 a i a_i ai

一棵好树需要满足对于所有顶点 v v v a v ≤ ∑ a u a_v\leq \sum a_u avau,其中顶点 u u u是顶点 v v v的直接孩子,即存在一条边连接 u u u v v v

每次操作可以使得一个顶点的值加一,问最少需要多少次操作才能使得该棵树为好树。

数据范围: 2 ≤ n ≤ 5000 , 0 ≤ a i ≤ 1 0 9 2\leq n\leq 5000,0\leq a_i\leq 10^9 2n5000,0ai109

Solution

b u = ∑ a v − a u b_u=\sum a_v -a_u bu=avau,叶子节点记为 + ∞ +\infty + h i h_i hi 为顶点的深度。问题转化成使得 b i ≥ 0   ( 1 ≤ i ≤ n ) b_i\geq0\ (1\leq i\leq n) bi0 (1in) 需要的最小操作次数。

先从特殊情况开始考虑,假设此时是以 u u u为根的树,其子树均为好树,只有 b u < 0 b_u<0 bu<0

若节点 u u u 的孩子 b v > 0 b_v>0 bv>0,那么 b u b_u bu 每次加一只需要操作一次,一共能加 b v b_v bv 次;而如果 b v = 0 b_v=0 bv=0,那么 b u b_u bu 要想加一,就必须顺着树传递下去,对路径上的节点依次执行加一操作,直到找到 b i > 0 b_i>0 bi>0 的节点,需要执行的操作次数为 h i − h u h_i-h_u hihu

因此要使得该树变成好树的最优方案就是按 b u b_u bu 加一需要的代价从小到大执行,直到 b u b_u bu 恰好等于0。

对于一般的情况可以先从叶子节点开始往根节点遍历,这样每次遇到的都是上述的特殊情况。

时间复杂度: O ( n 2 ) O(n^2) O(n2)

Code

void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    vector<int> g[n + 1], h(n + 1, 0);
    for (int i = 2; i <= n; i++)
    {
        int p;
        cin >> p;
        g[p].push_back(i);
        h[i] = h[p] + 1;
    }
    for (int i = 1; i <= n; i++)
    {
        if (g[i].empty())
        {
            b[i] = inf;
            continue;
        }
        b[i] = -a[i];
        for (auto u : g[i])
        {
            b[i] += a[u];
        }
        // printf("%lld ", b[i]);
    }
    // printf("\n");
    ll ans = 0;
    for (int i = n; i >= 1; i--)
    {
        queue<int> q;
        q.push(i);
        if (b[i] >= 0)
        {
            continue;
        }
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (auto v : g[u])
            {
                if (b[v] > 0)
                {
                    int d = min(-b[i], b[v]);
                    b[i] += d;
                    b[v] -= d;
                    ans += (ll)d * (h[v] - h[i]);
                }
                q.push(v);
            }
        }
    }
    printf("%lld\n", ans);
}
  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据提供的引用内容,Codeforces Round 511 (Div. 1)是一个比赛的名称。然而,引用内容中没有提供与这个比赛相关的具体信息或问题。因此,我无法回答关于Codeforces Round 511 (Div. 1)的问题。如果您有关于这个比赛的具体问题,请提供更多的信息,我将尽力回答。 #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[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^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces Round 867 (Div. 3)(A题到E题)](https://blog.csdn.net/wdgkd/article/details/130370975)[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^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[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^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值