文章目录
Educational Codeforces Round 101 (Rated for Div. 2)
A. Regular Bracket Sequence
题意: 就是给你一个由 ‘(’ ,’)’ 或 ‘?’ 组成的字符串 ,’?'替换为 '(’ 或 ‘)’ ,不能改变位置。
**题解: ** 看第一个和最后一个字符是否符合,并且长度是否是2的倍数就好了。原先用栈写的代码,去模拟整个过程,wa了一发,赛后分析是因为处理不了(?)?的输入清空,而且没有使用到只有2的(的情况。
**代码: **
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n, m, T;
int main() {
cin >> T;
while(T--) {
string s;
cin >> s;
if ((s.size() & 1) || s[0] == ')' || s.back() == '(') {
puts("NO");
continue;
}
puts("YES");
}
return 0;
}
B. Red and Blue
题意: 有一个数组,由标记为R或B的数字组成,现在这个数组丢了。但是给你了两组数组R跟B,顺序为他们在原数组的出现顺序,现在让你把他们排回去,找出一种排序方式使得f(a)=max(0,a1,(a1+a2),(a1+a2+a3),…,(a1+a2+a3+⋯+an+m))最大。
**题解: ** 要和原数组的出现顺序一致,那么就是把2个数组按照原来的位置拼接在一起。那现在使得拼接出来的数组的某个前缀最大,所有的情况一共有n * m种,其中最大的情况就是2个最大的前缀相加。
**代码: **
#include <bits/stdc++.h>
using namespace std;
int n, m, T;
const int INF = 1e9;
int main() {
cin >> T;
while (T--) {
cin >> n;
int num;
int sum1 = 0;
int res1 = -INF;
for (int i = 0; i < n; i++) {
cin >> num;
sum1 += num;
res1 = max(res1, sum1);
}
if (res1 < 0) res1 = 0;
cin >> m;
int sum2 = 0;
int res2 = -INF;
if (m == 0) res2 = 0;
for (int i = 0; i < m; i++) {
cin >> num;
sum2 += num;
res2 = max(res2, sum2);
}
if (res2 < 0) res2 = 0;
printf("%d\n", res1 + res2);
}
return 0;
}
C. Building a Fence
题意: 给你一堆高度去建围栏,这些围栏必须有公共边,第一个和最后一个围栏必须挨着地面,其他围栏可以浮空,但不能超过k - 1
**题解: ** 维护low和high作为围栏的最小、最大值,每次都更新下围栏的上下界。
**代码: **
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n, m, T, h[MAXN], k;
int main() {
cin >> T;
while(T--) {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i) scanf("%d", h + i);
int flg = 1, low = h[1], high = h[1] + k;
for (int i = 2; i <= n - 1; ++i) {
if (high <= h[i] || low >= h[i] + 2 * k - 1) {
flg = 0;
break;
}
low = max(h[i], low - k + 1);
high = min(h[i] + 2 * k - 1, high + k - 1);
}
if (high <= h[n] || low >= h[n] + k) flg = 0;
if (flg) puts("YES");
else puts("NO");
}
return 0;
}
D. Ceil Divisions
题意: 给定一个有n个数的a数组,每次操作选择两个数x,y(x≠y),使得ax=⌈ax/ay⌉。
要求执行不多于n+5个操作,将a数组变成有n-1个1和1个2的数组。输出依次进行的操作,不要求最小化。
**题解: ** 可以构造出 2 1 2^1 21, 2 4 2^4 24, 2 8 2^8 28, n,这4个数字,对于这4个数字之间的数字全部除于n,那么就会全部变成1;对于这4个数字之间,大的除以小的,最多只会要2次就能变成1。最后这个操作到达2结束。
**代码: **
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const N = 3e5 + 10;
int n, m, T;
int num[100];
int main() {
cin >> T;
num[1] = 2;
for (int i = 2; i <= 5; i++) num[i] = num[i - 1] * num[i - 1];
while (T--) {
int res = 0;
scanf("%d", &n);
int pos = 2;
for (int i = 2; i < n; i++) {
int flg = 0;
for (int j = 1; j <= 5; j++)
if (i == num[j]) {
flg = 1;
pos = j;
}
if (flg) continue;
res++;
}
res += 2;
for (int i = pos; i >= 2; i--) res += 2;
printf("%d\n", res);
for (int i = 2; i < n; i++) {
int flg = 0;
for (int j = 1; j <= 5; j++) {
if (i == num[j]) {
flg = 1;
pos = j;
}
}
if (flg) continue;
printf("%d %d\n", i, n);
}
printf("%d %d\n", n, num[pos]);
printf("%d %d\n", n, num[pos]);
for (int i = pos; i >= 2; i--) {
printf("%d %d\n", num[i], num[i - 1]);
printf("%d %d\n", num[i], num[i - 1]);
}
}
return 0;
}
E.A Bit Similar
题意: 给你一个长度为n的字符串s,要求找到一个长度为k的字符串,该字符串和s的所有长度为k的子串都至少有一个相同的字符
**题解: ** 我们可以把s的所有子串的反码都放进一个set内,则set内为与所有子串都不相同的集合,存储的时候只需要存储后30位。然后枚举所有情况,如果在集合没有找到,那么说明这个字符串可以。
**代码: **
#include <bits/stdc++.h>
using namespace std;
int n, k;
string s;
int main() {
int q; cin >> q;
while(q--) {
cin >> n >> k;
cin >> s;
int bit = min(k, 30);
set<int> st;
int pre = 0;
for(int i = k - 1; i < s.size(); i++) {
if(pre < i - k + 1) pre++;
while(s[pre] == '1' && pre < i) pre++;
if(pre < i - bit + 1) continue;
int val = 0;
for(int j = i - bit + 1; j <= i; j++) val = (val << 1) | (s[j] == '0');
st.insert(val);
}
bool flg = false;
for(int ans = 0; ans < 1 << bit; ans++)
if(st.find(ans) == st.end()) {
cout << "YES" << endl;
for(int j = 0; j < k - bit; j++) cout << "0";
for(int j = bit - 1; j >= 0; j--) cout << (ans >> j & 1);
cout << endl;
flg = true;
break;
}
if(!flg) cout << "NO" << endl;
}
return 0;
}