VP Educational Codeforces Round 35 (Rated for Div. 2)
A. Nearest Minimums
题意:求相隔最近的两个最小的数。
记录上一个出现的位置,遍历即可。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int min = *std::min_element(a.begin(), a.end());
int ans = n;
for (int i = 0, last = -n; i < n; ++ i) {
if (a[i] == min) {
ans = std::min(ans, i - last);
last = i;
}
}
std::cout << ans << "\n";
}
B. Two Cakes
枚举。
点击查看代码
void solve() {
int n, a, b;
std::cin >> n >> a >> b;
int ans = 0;
if (a >= n || b >= n) {
ans = 1;
}
for (int i = 1; i < n; ++ i) {
int j = n - i;
if (a < i || b < j) {
continue;
}
ans = std::max(ans, std::min(a / i, b / j));
}
std::cout << ans << "\n";
}
C. Three Garlands
题意:要求构造三个等差数列,使得它们可以覆盖所有正整数。现在已经给出了三个公差,求三个首项。
正解似乎是算式子。但我直接枚举了,因为显然首项都很小。那么我们枚举三个首项,然后判断1到100里的数有没有都出现过。
点击查看代码
void solve() {
int a, b, c;
std::cin >> a >> b >> c;
if (a == 1 || b == 1 || c == 1) {
std::cout << "YES\n";
return;
}
for (int x = 1; x <= 10; ++ x) {
for (int y = 1; y <= 10; ++ y) {
for (int z = 1; z <= 10; ++ z) {
bool flag = true;
for (int i = 1; i <= 100; ++ i) {
if ((i - x) % a && (i - y) % b && (i - z) % c) {
flag = false;
break;
}
}
if (flag) {
std::cout << "YES\n";
return;
}
}
}
}
std::cout << "NO\n";
}
D. Inversion Counting
题意:给你一个排列,每次翻转一个区间,求其逆序对的奇偶性。
只要求奇偶性,那么我们可以分析一下,显然翻转这个区间不会影响区间内的元素和区间外的元素的关系。那么只需要观察区间内的变化,发现原来的逆序对会变成正序对,正序对会变成逆序对。那么一个区间总共有\(\frac{len \times (len - 1)}{2}\)对元素,如果区间元素对是偶数个,那么逆序对个数和正序对个数奇偶性相同,翻转后奇偶性不变;如果区间对数是奇数个,那么逆序对个数和正序对个数奇偶性不同,翻转后奇偶性变化。
于是我们只需要关注区间对数。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int cnt = 0;
for (int i = 0; i < n; ++ i) {
for (int j = i + 1; j < n; ++ j) {
cnt += a[i] > a[j];
}
}
int flag = cnt & 1;
int q;
std::cin >> q;
while (q -- ) {
int l, r;
std::cin >> l >> r;
int len = r - l + 1;
if (len * (len - 1) / 2 & 1) {
flag ^= 1;
}
if (flag) {
std::cout << "odd\n";
} else {
std::cout << "even\n";
}
}
}
E. Stack Sorting
题意:有一个排列,这个排列可以用栈操作使得元素升序输出。现在给你前\(k\)个元素,你要构造后\(n-k\)个元素,使得字典序最大。
首先判断无解,用栈维护元素,如果想要升序输出,那么栈里的元素必须是降序存储。每次遇到最小的数就一直退栈。
然后对于后面的元素,优先给最大的就行了。
点击查看代码
void solve() {
int n, k;
std::cin >> n >> k;
std::set<int> s;
for (int i = 1; i <= n; ++ i) {
s.insert(i);
}
std::vector<int> ans(n);
for (int i = 0; i < k; ++ i) {
std::cin >> ans[i];
s.erase(ans[i]);
}
std::stack<int> stk;
int min = 1;
for (int i = 0; i < k; ++ i) {
if (stk.size() && ans[i] > stk.top()) {
std::cout << -1 << "\n";
return;
}
stk.push(ans[i]);
while (stk.size() && stk.top() == min) {
++ min;
stk.pop();
}
}
for (int i = k; i < n; ++ i) {
if (stk.empty()) {
ans[i] = *s.rbegin();
stk.push(ans[i]);
s.erase(ans[i]);
} else {
auto it = s.lower_bound(stk.top());
if (it == s.begin()) {
std::cout << -1 << "\n";
return;
}
-- it;
ans[i] = *it;
stk.push(*it);
s.erase(it);
}
while (stk.size() && stk.top() == min) {
++ min;
stk.pop();
}
}
for (int i = 0; i < n; ++ i) {
std::cout << ans[i] << " \n"[i == n - 1];
}
}