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];
    }
}
posted @ 2025-03-17 17:52  maburb  阅读(10)  评论(0)    收藏  举报