VP Educational Codeforces Round 27
A. Chess Tourney
题意:把一个数组分成两组,使得一个数组的每一个数都的大于另一个数组的每一个数。
排序后判断中间两个数是不是相等。
点击查看代码
void solve() {
int n;
std::cin >> n;
n <<= 1;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::sort(a.begin(), a.end());
if (a[n / 2] > a[n / 2 - 1]) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
}
B. Luba And The Ticket
题意:给你一个数字串,使得前三个数的和等于后三个数的和,求更改的数最小。
枚举每个数的取值。
点击查看代码
void solve() {
std::string s;
std::cin >> s;
int n = s.size();
int ans = 1e9;
for (int i = 0; i <= 9; ++ i) {
for (int j = 0; j <= 9; ++ j) {
for (int k = 0; k <= 9; ++ k) {
for (int x = 0; x <= 9; ++ x) {
for (int y = 0; y <= 9; ++ y) {
for (int z = 0; z <= 9; ++ z) {
if (i + j + k == x + y + z) {
ans = std::min(ans, (s[0] - '0' != i) + (s[1] - '0' != j) + (s[2] - '0' != k)
+ (s[3] - '0' != x) + (s[4] - '0' != y) + (s[5] - '0' != z));
}
}
}
}
}
}
}
std::cout << ans << "\n";
}
C. Two TVs
题意:若干个区间分成两组,每一组的区间都没有交集。
按右端点排序,维护两组的最大右端点,每次新加进来的区间放到右端点最小的组。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<std::pair<int, int>> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i].second >> a[i].first;
}
std::sort(a.begin(), a.end());
int r1 = -1, r2 = -1;
for (auto & [r, l] : a) {
if (r1 < r2) {
std::swap(r1, r2);
}
if (l > r1) {
r1 = r;
} else if (l > r2) {
r2 = r;
} else {
std::cout << "NO\n";
return;
}
}
std::cout << "YES\n";
}
D. Driving Test
题意很长,懒得说了。
模拟题。
维护超车不合法的贡献就是记录出现过的不让超车的次数。每次超车就加上这个次数,然后次数清零。遇到可以超车的标记也清零。
然后对于超速的处理,把每个速度限制加到栈里,每次把栈里小于车速的弹出来并计算贡献。遇到无限制标志就把栈情况。
点击查看代码
void solve() {
int n;
std::cin >> n;
const int inf = 1e9;
int limit = inf, speed = 0;
bool flag = true;
int flag_cnt = 0;
std::stack<int> stk;
int ans = 0;
while (n -- ) {
int t, s;
std::cin >> t;
if (t == 1) {
std::cin >> s;
speed = s;
while (stk.size() && stk.top() < speed) {
++ ans;
stk.pop();
}
} else if (t == 2) {
if (!flag) {
ans += flag_cnt;
flag_cnt = 0;
}
} else if (t == 3) {
std::cin >> s;
limit = s;
stk.push(limit);
while (stk.size() && stk.top() < speed) {
++ ans;
stk.pop();
}
} else if (t == 4) {
flag = true;
flag_cnt = 0;
} else if (t == 5) {
limit = inf;
while (stk.size()) {
stk.pop();
}
} else {
flag = false;
flag_cnt += 1;
}
}
std::cout << ans << "\n";
}
E. Fire in the City
题意:一个\(n \times m\)的矩阵有\(k + 1\)个点,每个点每秒会扩大一倍,覆盖一个\(2 \times t +1\)的矩阵。给出你\(k\)个点,还有一个点不知道,你需要确定整个矩阵被包含的最小时间。
如果已知所有点和时间,那么我们可以离散化加差分处理。把每个点当前的矩阵四个角及其周边的点加进来离散。然后把每个矩阵加一。差分后值是\(0\)的矩阵就没有被覆盖。此时如果想加进来一个点覆盖这些没有被覆盖的点,需要这些点形成的大矩阵能被整个点覆盖,可以直接找到每个边界的点根据距离判断。
那么到这个题,我们可以二分时间,然后就是上述操作去\(check\)。
点击查看代码
void solve() {
int n, m, k;
std::cin >> n >> m >> k;
std::vector<std::pair<int, int>> a(k);
for (int i = 0; i < k; ++ i) {
std::cin >> a[i].first >> a[i].second;
}
auto check = [&](int t) -> bool {
std::vector<int> X, Y;
for (auto & [x, y] : a) {
int x1 = std::max(1, x - t), x2 = std::min(n, x + t);
int y1 = std::max(1, y - t), y2 = std::min(m, y + t);
X.push_back(x1);
X.push_back(x2);
Y.push_back(y1);
Y.push_back(y2);
if (x1 > 1) {
X.push_back(x1 - 1);
}
if (x2 < n) {
X.push_back(x2 + 1);
}
if (y2 < m) {
Y.push_back(y2 + 1);
}
if (y1 > 1) {
Y.push_back(y1 - 1);
}
}
X.push_back(1); X.push_back(n);
Y.push_back(1); Y.push_back(m);
std::sort(X.begin(), X.end());
X.erase(std::unique(X.begin(), X.end()), X.end());
std::sort(Y.begin(), Y.end());
Y.erase(std::unique(Y.begin(), Y.end()), Y.end());
int N = X.size(), M = Y.size();
auto getx = [&](int x) -> int {
return std::lower_bound(X.begin(), X.end(), x) - X.begin() + 1;
};
auto gety = [&](int y) -> int {
return std::lower_bound(Y.begin(), Y.end(), y) - Y.begin() + 1;
};
std::vector d(N + 2, std::vector<int>(M + 2));
for (auto & [x, y] : a) {
int x1 = std::max(1, x - t), x2 = std::min(n, x + t);
int y1 = std::max(1, y - t), y2 = std::min(m, y + t);
x1 = getx(x1);
x2 = getx(x2);
y1 = gety(y1);
y2 = gety(y2);
++ d[x1][y1];
-- d[x1][y2 + 1];
-- d[x2 + 1][y1];
++ d[x2 + 1][y2 + 1];
}
for (int i = 1; i <= N; ++ i) {
for (int j = 1; j <= M; ++ j) {
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
}
}
int minx = N, maxx = 1, miny = M, maxy = 1;
for (int i = 1; i <= N; ++ i) {
for (int j = 1; j <= M; ++ j) {
if (d[i][j] == 0) {
minx = std::min(minx, i);
maxx = std::max(maxx, i);
miny = std::min(miny, j);
maxy = std::max(maxy, j);
}
}
}
return std::max(X[maxx - 1] - X[minx - 1], Y[maxy - 1] - Y[miny - 1]) + 1 <= t * 2 + 1;
};
int l = 0, r = std::max(n, m);
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
std::cout << l << "\n";
}