Codeforces Round #737 (Div. 2)
# | 题目 | 分数 | 是否AC |
---|---|---|---|
A | Ezzat and Two Subsequences | 800 | ✅ |
B | Moamen and k-subarrays | 1100 | ✅ |
C | Moamen and XOR | 1700 | ❌ |
D | Ezzat and Grid | 2200 | ❌ |
E | Assiut Chess | 2800 | ❌ |
A. Ezzat and Two Subsequences
题目类型 思维
题意
给定一个数组,将数组分为两个部分,就可以得到两部分平均数和的最大值。
分析
因为一个集合的平均数 v v v 一定满足 m i n ≤ v ≤ m a x min \leq v \leq max min≤v≤max。所以将数组分为其最大值一部分和其它值一部分所得的结果是最大的。
时间复杂度
O ( n ) O(n) O(n)
代码
public static void solve() throws IOException {
int n = nextInt();
int[] a = new int[n];
long sum = 0;
for (int i = 0; i < n; i++) {
a[i] = nextInt();
sum += a[i];
}
long Max = Long.MIN_VALUE;
for (int i = 0; i < n; i++) Max = Math.max(Max, a[i]);
double ans = Max + (double) (sum - Max) / (n - 1);
pw.println(String.format("%.10f", ans));
}
B. Moamen and k-subarrays
题目类型 思维 排序
题意
输入一个数组,判断能否将数组恰好分为 k k k 个子数组(连续的部分),并将这 k k k 个子数组进行重排使源数组变为升序。
分析
如果源数组中一个连续的部分和源数组升序排序后的状态是相同的,则这个部分可以分成一个子数组。按照这个方式对源数组进行划分,统计划分出子数组的个数 c n t cnt cnt, 这个数是划分的最少个数,如果 k < c n t k < cnt k<cnt 则不能重排使其变为升序,否则一定可以。
时间复杂度
O ( n log n ) O(n\log n) O(nlogn)
代码
public static void solve() throws IOException {
int n = nextInt();
int k = nextInt();
int[] a = new int[n];
int[] b = new int[n];
for (int i = 0; i < n; i++) a[i] = nextInt();
System.arraycopy(a, 0, b, 0, n);
shuffle(b);
Arrays.sort(b);
int cnt = 0;
for (int i = 0; i < n; i++) {
int j = binarySearch(b, 0, n - 1, a[i]);
while (i < n && j < n && a[i] == b[j]) {
i++;
j++;
}
i--;
cnt++;
}
if (cnt <= k) pw.println("YES");
else pw.println("NO");
}
public static void shuffle(int[] a) {
for (int i = 0; i < a.length; i++) {
int rand = (int) (Math.random() * a.length);
int temp = a[rand];
a[rand] = a[i];
a[i] = temp;
}
}
public static int binarySearch(int[] a, int l, int r, int aim) {
while (l < r) {
int mid = l + r >> 1;
if (a[mid] >= aim) r = mid;
else l = mid + 1;
}
return r;
}