Codeforces Round #627 (Div. 3) 题解
Codeforces Round #627 (Div. 3)
A. Yet Another Tetris Problem
题意:给你一堆俄罗斯方块,询问在只有 \(1\times 2\) 的方块情况下能否消除所有方块。
分析:看懂题目比做题还麻烦。
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define SIZE 200010
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define mp make_pair
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, t, a[SIZE];
int main() {
io(); cin >> t;
rep(ii, 1, t) {
cin >> n;
rep(i, 1, n) cin >> a[i];
bool f = true;
rep(i, 2, n) {
if ((a[i] - a[i - 1]) & 1) {
f = false;
break;
}
}
cout << (f ? "YES\n" : "NO\n");
}
}
B. Yet Another Palindrome Problem
题意:询问是否存在长度大于等于三的回文子序列(不连续)。
分析:由于不连续的条件,我们只需要找是否存在非相邻的相同字符即可。
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define SIZE 200010
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define mp make_pair
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, t, a[SIZE];
int main() {
io(); cin >> t;
rep(ii, 1, t) {
cin >> n;
map<int, vector<int> > MP;
bool f = false;
rep(i, 1, n) cin >> a[i], MP[a[i]].emplace_back(i);
for (auto i : MP) {
if (i.second.size() > 2) {
f = true;
break;
}
if (i.second.size() == 2 && abs(i.second[0] - i.second[1]) > 1) {
f = true;
break;
}
}
cout << (f ? "YES\n" : "NO\n");
}
}
C. Frog Jumps
题意:给定一个字符串 \(s\) 。 一只青蛙在 \(x=0\) 处,一次最大跳跃距离为 \(d\) ,当它跳到位置 \(x=i\) 时,如果 \(s[i]=R\) 那它能继续向右跳,若 \(s[i]=L\) 那它只能向左跳,询问使得青蛙能够跳到 \(x=n+1\) 位置的 \(d_{min}\) 。
分析:贪心,求两个字符 \(R\) 之间的最大距离。
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define SIZE 200010
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define mp make_pair
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, t, a[SIZE];
int main() {
io(); cin >> t;
rep(ii, 1, t) {
string s; cin >> s;
s += 'R';
int pre = 0, mind = -1;
rep(i, 1, s.length()) {
if (s[i - 1] == 'R') {
mind = max(mind, i - pre);
pre = i;
}
}
cout << (mind == -1 ? (s.length() + 1) : mind) << '\n';
}
}
D. Pair of Topics
题意:给定两个数组 \(a\) 和 \(b\) ,询问满足 \(a_i+a_j>b_i+b_j(i<j)\) 的二元组 \((i,j)\) 数量。
分析:明显的二分:\(a_i+a_j>b_i+b_j\Leftrightarrow a_i-b_i>-(a_j-b_j)\) 。于是只需要预处理一个数组 \(c_i=a_i-b_i\) 。
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define SIZE 200010
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define mp make_pair
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
ll n, a[SIZE], b[SIZE],ans;
vector<ll> vec;
int main() {
io(); cin >> n;
rep(i, 1, n) cin >> a[i];
rep(i, 1, n) cin >> b[i];
rep(i, 1, n) vec.emplace_back(a[i] - b[i]);
sort(vec.begin(), vec.end());
rep(i, 0, (vec.size() - 1)) {
int now = vec[i];
if (now > 0) ans += (n - 1 - i);
else {
int pos = lower_bound(vec.begin(), vec.end(), 1 - now) - vec.begin();
ans += max(0ll, (n - pos));
}
}
cout << ans;
}
E. Sleeping Schedule
题意:\(Vova\) 一共要睡觉 \(n\) 次,每次都会睡满一整天,每天时长 \(h\) 个小时,如果 \(Vova\) 的入睡时间在 \([l,r]\) 范围内则之称为一次好的睡眠。现在已知 \(Vova\) 第 \(i\) 次睡眠前,她能控制自己醒着 \(a_i\) 或者 \(a_i - 1\) 个小时。求好的睡眠最大值。
分析:注意到 \(n,h\leq 2000\) ,直接枚举时间进行 \(dp\) 。设第 \(i\) 次睡眠 \(j\) 时段的最大值为 \(dp[i][j]\) ,则有: \(dp[i][(j+t)modh] = max(dp[i][(j+t)modh],dp[i-1][j]+(l\leq (j+t)modh\leq r))\),\((t=a_i\) \(or\) \(a_i-1)\) 。emmm,好像就结束了。
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define SIZE 2010
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define mp make_pair
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, h, l, r, ans = -1;
int a[SIZE], dp[SIZE][SIZE];
int main() {
io(); cin >> n >> h >> l >> r;
rep(i, 1, n) cin >> a[i];
rep(i, 0, 2000) rep(j, 0, 2000) dp[i][j] = -1;
dp[0][0] = 0;
rep(i, 1, n) {
i = i;
rep(j, 0, (h - 1)) dp[i][j] = -1;
rep(j, 0, (h - 1)) {
if (dp[i - 1][j] == -1) continue;
rep(t, (a[i] - 1), a[i]) {
int k = (j + t) % h;
dp[i][k] = max(dp[i][k], dp[i - 1][j] + (l <= k && k <= r));
}
}
}
rep(i, 0, h) ans = max(ans, dp[n][i]);
cout << ans;
}
F. Maximum White Subtree
题意:给定一棵无根树,每个节点都染色为白色或黑色,对每个节点询问:包含当前节点的任意子树中(因为是无根树,实际上就是连通块) \(cnt_w-cnt_b\) 的最大值,即白色点数减黑色点数的最大值。
分析:标准的换根树形 \(dp\) ,我们任取一点作为根,此时对于任意节点我们能够简单地推出以下递推式: \(dp_{now}=\underset{i\in children(now)}\sum{max(0,dp[i])}\) 。然后考虑换根,我们考虑交换 \(now\) 节点和他的一个子节点 \(to\) 之后会发生什么变化:显然这个交换只会影响 \(now\) 和 \(to\) 这两个节点,其他节点任然作为子节点不受影响。得到第二组树形 \(dp\) 转移式:\(dp_{now}=dp_{now}-max(0,dp[to])\) ; \(dp_{to}=dp_{to}+max(0,dp_{now})\) 。
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define SIZE 200010
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define mp make_pair
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n;
int a[SIZE], dp[SIZE], ans[SIZE];
vector<int> vec[SIZE];
void dfs(int now, int pa) {
dp[now] = a[now];
for (auto i : vec[now]) {
if (i == pa) continue;
dfs(i, now);
dp[now] += max(0, dp[i]);
}
}
void dfs2(int now, int pa) {
ans[now] = dp[now];
for (auto i : vec[now]) {
if (i == pa) continue;
dp[now] -= max(0, dp[i]);
dp[i] += max(0, dp[now]);
dfs2(i, now);
dp[i] -= max(0, dp[now]);
dp[now] += max(0, dp[i]);
}
}
int main() {
io(); cin >> n;
rep(i, 1, n) {
int x; cin >> x;
a[i] = (x ? 1 : -1);
}
rep(i, 1, (n - 1)) {
int x, y; cin >> x >> y;
vec[x].emplace_back(y);
vec[y].emplace_back(x);
}
dfs(1, 0);
dfs2(1, 0);
rep(i, 1, n) cout << ans[i] << ' ';
}
这场 \(div3\) 好像特别简单。。。