Codeforces Round #735 (Div. 2)

A

考虑钦定 \(l\),容易发现,\(r\) 向右扩展不一定带来更大的区间最大值,而可能带来更小的区间最小值。所以,只有 \(a_r\) 大于此前区间最大值,才可能带来更大的答案;只有 \(a_l\) 是区间最小值,\([l + 1, r]\) 的答案才可能会大于 \([l, r]\) 的答案。

但这样貌似还是不可做。考虑答案子序列的长度,例如:有三个可能的答案区间 \([l, l + 1]\)\([l, l + 2]\)\([l + 1, l + 2]\)。当 \(a_{l + 2}\) 成为了第二个区间的最小值,显然不会比另外两个区间答案的最大值更优;当 \(a_{l + 2}\) 成为了第二个区间的最大值,同理。以此类推,我们只需要用长度为 \(2\) 的序列更新答案。

代码:

#include <stdio.h>
 
typedef long long ll;
 
int a[100007];
 
inline ll max(ll a, ll b){
	return a > b ? a : b;
}
 
int main(){
	int t;
	scanf("%d", &t);
	for (int i = 1; i <= t; i++){
		int n;
		ll ans = 0;
		scanf("%d", &n);
		for (int j = 1; j <= n; j++){
			scanf("%d", &a[j]);
		}
		for (int j = 1; j < n; j++){
			ans = max(ans, (ll)a[j] * a[j + 1]);
		}
		printf("%lld\n", ans);
	}
	return 0;
}

B

由于 \(n\) 很小,考虑乱搞做法:对于每一个 \(1 \leq i \leq n - k\),向后扫 \(k\) 个。不会证明。时间复杂度为 \(O(tnk)\)。官方题解中有 \(O(tk^2)\) 做法。

代码:

#include <stdio.h>
 
typedef long long ll;
 
int a[100007];
 
inline ll max(ll a, ll b){
	return a > b ? a : b;
}
 
int main(){
	int t;
	scanf("%d", &t);
	for (int i = 1; i <= t; i++){
		int n, k;
		ll ans = -9e18;
		scanf("%d %d", &n, &k);
		for (int j = 1; j <= n; j++){
			scanf("%d", &a[j]);
		}
		for (int j = 1; j < n; j++){
			for (int x = 1; x <= k && j + x <= n; x++){
				ans = max(ans, (ll)j * (j + x) - (ll)k * (a[j] | a[j + x]));
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

C

题目显然是求一个最小的 \(x\),使 \(n \operatorname{xor} x > m\)

\(n > m\),显然答案为 \(0\);否则设 \(k = m + 1\)\(a_i\) 表示 \(a\) 在二进制表示下的第 \(i\) 位,将原式转换为 \(n \operatorname{xor} x \geq k\)

  1. \(n_i < k_i\)

直接令 \(x_i = 1\) 即可。

  1. \(n_i = k_i\)

直接令 \(x_i = 0\) 即可。

  1. \(n_i > k_i\)

显然已经满足条件,直接 break 即可。

代码:

#include <stdio.h>
#include <math.h>

int main(){
	int t;
	scanf("%d", &t);
	for (int i = 1; i <= t; i++){
		int n, m, ans = 0;
		scanf("%d %d", &n, &m);
		if (n > m){
			printf("0\n");
			continue;
		}
		m++;
		for (int j = log2(m); j >= 0; j--){
			int x = n >> j & 1, y = m >> j & 1;
			if (x < y){
				ans |= 1 << j;
			} else if (x > y){
				break;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

D

这道题显然要让我们把若干单个字符组合起来。

显然,单个字符的组合中长度为奇数的字符出现次数的奇偶性与总长度相同,否则相异。

为了让总出现次数为奇数,我们可以让长度为一奇一偶的字符串组合起来啊!

于是我们令 \(m = \lfloor \frac{n}{2} \rfloor\),首先构造 \(m\) 个 a,然后根据 \(n\) 的奇偶性构造 b 或 bc,最后构造 \(m - 1\) 个 a 即可。

代码:

#include <stdio.h>

int main(){
	int t;
	scanf("%d", &t);
	for (int i = 1; i <= t; i++){
		int n;
		scanf("%d", &n);
		if (n == 1){
			printf("a\n");
		} else {
			int m = n / 2;
			for (int j = 1; j < m; j++){
				printf("a");
			}
			printf("b");
			if (n % 2 == 1) printf("c");
			for (int j = 1; j <= m; j++){
				printf("a");
			}
			printf("\n");
		}
	}
	return 0;
}
posted @ 2021-07-30 09:12  LovelyLeasier  阅读(50)  评论(0)    收藏  举报