Codeforces Round 890 (Div. 2)

A.Tales of a Sort

题目大意

Alphen has an array of positive integers a of length n.

Alphen can perform the following operation:

  • For all i from 1 to n, replace ai with max(0,ai1) .

Alphen will perform the above operation until a is sorted, that is a satisfies a1a2an. How many operations will Alphen perform? Under the constraints of the problem, it can be proven that Alphen will perform a finite number of operations.

思路

记录最大的逆序对的值即可

#include <bits/stdc++.h> using namespace std; const int N = 550; int a[N]; void solve() { int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; int ans = 0; for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) { if (a[i] > a[j]) ans = max(ans, a[i]); } cout << ans << endl; } int main() { int t; cin >> t; while (t--) solve(); return 0; }

B.Good Arrays

题目大意

Let's call an array of positive integers b of length n good if:

  1. aibi for all i from 1 to n ,
  2. a1+a2++an=b1+b2++bn.

思路

这道题将非 1 的数把值累加到 1 上面,让自己等于 1, 然后 1 变成非 1

#include <bits/stdc++.h> using namespace std; typedef long long LL; void solve() { int n; cin >> n; LL cnt1 = 0, sum = 0; for (int i = 1; i <= n; i++) { int x; scanf("%d", &x); if (x == 1) cnt1++; else sum += (x - 1); } if (n == 1) { puts("NO"); return; } if (sum >= cnt1) { puts("YES"); return; } else { puts("NO"); return; } } int main() { int t; cin >> t; while (t--) solve(); return 0; }

C.To Become Max

题目描述

You are given an array of integers a of length n .

In one operation you:

  • Choose an index i such that 1in1 and aiai+1 .
  • Increase ai by 1 .

Find the maximum possible value of max(a1,a2,an) that you can get after performing this operation at most k times.

输入格式

Each test contains multiple test cases. The first line of input contains a single integer t ( 1t100 ) — the number of test cases. The description of the test cases follows.

The first line of each test case contains two integers n and k ( 2n1000 , 1k108 ) — the length of the array a and the maximum number of operations that can be performed.

The second line of each test case contains n integers a1,a2,,an ( 1ai108 ) — the elements of the array a .

It is guaranteed that the sum of n over all test cases does not exceed 1000 .

输出格式

For each test case output a single integer — the maximum possible maximum of the array after performing at most k operations.

样例 #1

样例输入 #1
6 3 4 1 3 3 5 6 1 3 4 5 1 4 13 1 1 3 179 5 3 4 3 2 2 2 5 6 6 5 4 1 5 2 17 3 5
样例输出 #1
4 7 179 5 7 6

提示

In the first test case, one possible optimal sequence of operations is: [1,3,3][2,3,3][2,4,3][3,4,3][4,4,3] .

In the second test case, one possible optimal sequence of operations is: [1,3,4,5,1][1,4,4,5,1][1,5,4,5,1][1,5,5,5,1][1,5,6,5,1][1,6,6,5,1][1,7,6,5,1] .

思路

我们二分答案,下界设为 0,而 max(a1,an)+k 作为上界。

ba 在执行 k 次操作后的数组。假设对于一个数 x,我们想要检查是否可以在 k 次操作中得到max(b1,bn)x。也就是说,通过 k 次操作使得存在某个索引 i 使得 bix

因此,让我们从遍历一下 b 数组 ,看看是否可以在 k 次操作中使得 bix

f(i,y) 为使得 biy 所需的最小操作数。那么有:

f(i,y)=0,yaif(i,y)=yai+f(i+1,y1)1aif(i,y)=+i=ny>ai

显然计算 f(i,x) 最坏情况下需要 O(n) 的时间。因此,我们看看 i=1nfi,xk

如果操作次数 k,那么在 k 次操作中可能存在某个 bix,并在更新当前答案后让 l=mid。否则这个 x 没有办法满足,让 r=mid。复杂度:O(n2logA),其中 Aaik 的最大可能值。

image-20230806223152909

我们这里再来看

一个优化空间的思路,因为我们只需要计算所有 f 值的和,所以 O(1) 空间复杂度就可以了。

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2005; vector<ll> a(N); ll n, k; bool check(ll x) { for (int i = 1; i <= n; i++) { vector<ll> minneed(n + 1); minneed[i] = x; ll ut = 0; for (int j = i; j <= n; j++) { if (minneed[j] <= a[j]) break; if (j == n) { ut = k + 1; break; } ut += minneed[j] - a[j]; minneed[j + 1] = max(0ll, minneed[j] - 1); } if (ut <= k) return true; } return false; } void solve() { cin >> n >> k; ll maxnum = 0; for (int i = 1; i <= n; i++) { cin >> a[i]; maxnum = max(maxnum, a[i]); } // cout << *max_element(a.begin(), a.end()) + k + 1 << endl; ll l = -1, r = maxnum + k + 1, ans = 0; // cout << r << endl; while (l + 1 < r) { ll mid = (l + r) >> 1; if (check(mid)) ans = mid, l = mid; else r = mid; } cout << l << endl; } int main() { int t; cin >> t; while (t--) solve(); return 0; }

E1 .PermuTree(easy version)

题目大意

给定一棵以 1 为根的有根树,你需要给出一个 1n 的排列 a,最大化二元组 (u,v) 的数量,满足 au<alca(au,av)<av,输出这个最大值。

2n5000

思路

这道题等价于给每个点重新赋一个值 ai 然后满足条件即可

对于一个节点 i ,我们可以使得一部分 i 的子树的 a 值均小于 ai,一部分子树的 a 值均大于 ai ,因为 a 是排列所以所有 ai 的值都不会重复

易得两棵子树的节点个数和的乘积就是 i 的贡献(乘法原理)

我们设 f[x]代表某个节点 u 是否有一个子树或者多个子树的节点的个数和为 xsizi 为以 i 为根的子树的节点个数

那么当 u 有集合节点个数为 i 时,易得这时分界后 u 的贡献为 i×(sizu1i) 减去 1 是因为根节点不能算。

然后对于每一个 u 递归求和即可,不能忘了把 f 初始化为 0.

#include <bits/stdc++.h> using namespace std; const int N = 5e4 + 50; vector<int> e[N]; bool f[N]; int a[N], siz[N]; int n; void dfs0(int u, int fa) { siz[u] = 1; if (e[u].empty()) { siz[u] = 1; return; } for (auto nxt : e[u]) { if (u == fa) continue; dfs0(nxt, u); siz[u] += siz[nxt]; } return; } int ans = 0; void dfs1(int u, int fa) { f[0] = 1; // f为是否存在一个子树大小为u for (auto nxt : e[u]) { if (u == fa) continue; for (int j = siz[u]; j >= siz[nxt]; j--) f[j] |= f[j - siz[nxt]]; //如果去掉这个子树有值,就把子树siz[nxt]加上 } int bst = 0; for (int i = 1; i <= siz[u]; i++) if (f[i]) bst = max(bst, i * (siz[u] - 1 - i)); ans += bst; memset(f, 0, sizeof(f)); for (auto nxt : e[u]) { if (u == fa) continue; dfs1(nxt, 1); } return; } int main() { cin >> n; for (int i = 2; i <= n; i++) { int x; scanf("%d", &x); e[x].emplace_back(i); } dfs0(1, 0); dfs1(1, 0); cout << ans << endl; return 0; }

__EOF__

本文作者ljfyyds
本文链接https://www.cnblogs.com/ljfyyds/p/17611869.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ljfyyds  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示